sharedMaterial 

머테리얼의 속성을 변경할때 SharedMaterial으로 색상을 바꾼다던지 쉐이더코드의 프로퍼티값들을 변경한다. 그런데 이 런타임중에 변경된 머테리얼의 값들은 종료해도 바뀐 값 그대로 유지된다. 이것을 봤을때 Material에셋과 대응한다고 볼 수 있다.

같은 머테리얼을 가지고 있는 오브젝트

sharedMaterial을 사용하면 같은 머테리얼을 사용하는 모든 오브젝트가 변경된다. 예를들어 플레이어가 공격한 몬스터에게 림라이트효과를 주고 싶어 피격받은 몬스터의 Rim의 굵기를 변경했는데, 주위 모든 몬스터들의 Rim의 굵기가 변경되는것이다. => sharedMaterial을 참조하여 렌더링하기 때문 (배치 렌더링)

하지만 피격한 몬스터의 Rim만 변경을 원하기에 Renderer.material로 특정 오브젝만 변경할 수 있다. 

복사본을 생성(Instance)하는 Renderer.material

값을 변경을 하지 않아도 Renderer.material을 참조하는 순간!, 사본이 생성된다. 당연히 사본을 생성했기에 배치 랜더링이 되지않는다. 

해결법은 Material Property Block

 

 

학습참고

http://thomasmountainborn.com/2016/05/25/materialpropertyblocks/

https://docs.unity3d.com/kr/530/ScriptReference/MaterialPropertyBlock.html

https://cacodemon.tistory.com/entry/material-%EA%B3%BC-sharedMaterial-%EA%B7%B8%EB%A6%AC%EA%B3%A0-Material-Property-Block

반응형

Game logic


Update

호출되는 시점 :  스크립트가 활성화 된 경우 매프레임마다 호출

 

Fire Animation Eevents

호출되는 시점 :  마지막 Update시간과 최신 Update업데이트 시간사이에 모든 클립에서 애니메이션이벤트를 호출

 

OnAnimatorMove 

호출되는 시점 :  Update 프레임마다 Animator컴포넌트에 대해 한 번 호출

 

OnAnimatorIK

호출되는 시점 :  Update 프레임마다 Animator컴포넌트에 대해 한 번 호출

 

LateUpdate

호출되는 시점 : Update가 끝난 후 프레임당 한 번 호출

특징

1. Update에서 수행된 모든 계산은 LateUpdate가 시작 할 때 완료 됨

2. 일반적으로 3인칭 카메라에 사용된다.

(캐릭터를 움직이고 Update방향을 카메라 움직임과 로테이션 계산을 수행하는 경우 LateUpdate에서 카메라로 그 위치와 방향에 맞게 움직이도록)

 


 

Scene rendering


OnWillRenderObject

호출되는 시점 : 카메라에 오브젝트가 표시되면 각 카메라에 한 번 호출

특징

1. 스크립트가 활성화 되어있어야 호출됨

2. 모든 컬링된 객체들을 렌더링하기 바로 직전의 과정인 컬링 처리중에 호출

 

OnPreCull

호출되는 시점 : 카메라에서 장면을 컬링하기 전에 호출(프로스터 컬링)

특징

1. 카메라에 붙어있는 스크립트에만 호출

2. 카메라의 속성을 바꾸고싶을때 사용하면 좋음

 

OnBecameVisible / OnBecameInvisible

호출되는 시점 : 카메라에 표시되거나/표시되지 않을 때 호출

 

OnPreRender

호출되는 시점 : 카메라가 씬 렌더링을 렌딩하기 전에 호출

특징

1. yield 사용 가능

2. 스크립트는 카메라에 붙어있어야함 

 

OnRenderObject(queueIndex:int)

호출되는 시점 : 오브젝트가 렌더링처리 된 후 호출

특징

1. queueIndex은 해당 오브젝트를 렌더링할 때 사용하는 렌더 큐의 값

 

OnPostRender

호출되는 시점 : 카메라가 씬 렌더링을 마친 후 호출

특징

1. 카메라에 붙어있는 스크립트에만 호출

2. 해당 카메라가 모든 오브젝트를 렌더링한 후 호출

 

OnRenderImage

호출되는 시점 : 씬 렌더링이 완료된 후 호출

 


 

Gizmo rendering


OnDrawGizmos

특징

1. 시각화 목적으로 씬 뷰에 기즈모를 그릴 때 사용


 

End of frame


yield WaitForEndOfFrame

호출되는 시점 : 하나의 프레임이 완전히 종료될 때 호출 

특징

1.  Update,LateUpdate이벤트가 모두 실행되고 화면에 렌더링이 끝난 이후 호출


 

Decommissioning


OnDisable

호출되는 시점 : 스크립트가 비 활성화 되거나 오브젝트가 비 활성 상태가 될 때 호출

특징

1. 오브젝트가 제거되는 경우에도 호출

2. 삭제를 위한 작업에 사용

3. 에디터모드일때 스크립트가 다시 로드되는 경우에도 호출

4. Start와 달리 코루틴 사용할 수 없음

OnDestroy

호출되는 시점 : 오브젝트 존재의 마지막 프레임 업데이트를 마친 후 에 호출

특징

1. 씬 게임이 종료될 때 도 발생

2. 오브젝트가 상태가 활성화 상태였던 경우에만 호출

 

반응형

프로젝트를 하면서  유니티 어떤 함수가 먼저 호출 될까? 라는 생각을 했지만  순서의 영향이 주는 프로젝트가 아니어서 넘어갔었는데 이참에 정리해보았다.

 

함수호출 순서로(위에서 부터 먼저 호출)

 

Initializion (초기화부분)

 


Awake

호출되는 시점 :  스크립트 객체가 로딩될 때, 단 한번 호출됨

특징

1.  모든 오브젝트가 초기화 된 후 호출된다.

2. Start함수 전에 호출된다.

3. coroutine동작 불가능

 

OnEnable

호출되는 시점 :  스크립트가 켜질 때

특징

1.  플레이모드 중에 스크립트를 편집할 경우, 편집이 끝난 후 스크립트가 다시 로딩되면 호출됨(Awake와 Start는 호출되지 않음)

2.   Awake함수 호출 후  호출됨 

 

Start

호출되는 시점 :  Update함수가 처음 호출 될 때 Update함수 직전에, 단 한번 호출됨

특징

1.  Awake와 다르게  start함수는 스크립트가 켜져있을 때 호출된다. (Awake는 스크립트가 꺼진 상태에도 호출됨)

2. Awake함수는 항상 Start함수 호출되기 전에 호출 된다.


 

 

Physics (물리)


FixedUpdate

호출되는 시점 :  스크립트가 켜져 있을 때 매프레임마다 호출

특징

1.  설정한 값에  따라 일정한 간격으로 호출된다.

2. 모든 물리계산 업데이트는 FixedUpdate후 즉시 발생된다.

3. 일정한 시간으로 호출되기에 Time.deltaTime을 곱할 필요 없다.

4.  Rigidbdoy를 다룰 때  일정한 힘을 가할 때, Update함수 대신에 사용 

(불규칙적인 Update에서는 물리엔진충돌 검사 등이 잘 안될 수 있다.)  

 

yield WaitForFixedUpdate (코루틴)

호출되는 시점 :  모든 FixedUpdate가 모든 스크립트에 호출된 후 

특징

1.  당연히 yield코루틴 명령문에서만 사용 가능

 

OnTriggerXXX, OnCollisionXXX

특징은 여기서 정리했다.

https://funfunhanblog.tistory.com/13

 

유니티) 충돌체크 OnTriggerEnter , OnCollisionEnter (Collider, Collision) #2Roll a Ball 로 연습하기

OnTrigger , OnCollision 비교하기 Collider 유니티에서 충돌체크를 하기 위한 필요한 컴포넌트이다. 3D오브젝트를 생성하면 Collider가 자동적으로 추가 되어있다. 먼저 Trigger에 대해 살펴보자 1) void OnTrigg..

funfunhanblog.tistory.com

 


 

 

Input events


OnMouseXXX

특징 : 마우스입력으로 호출되는 이벤트함수

 


Unity) 유니티 이벤트실행순서 / 플로우차트(Script Lifecycle Flowchart) #2

https://funfunhanblog.tistory.com/253

 

 

 

 

 

유니티 - 매뉴얼: 이벤트 함수의 실행 순서

자동 메모리 관리를 이해하기 이벤트 함수의 실행 순서 Unity 스크립팅시, 미리 정의된 순서대로 실행되는 많은 이벤트 함수가 있습니다. 아래에서는, 실행 순서를 설명합니다. 에디터 __ Reset : __ Reset은 개체가 처음 연결되었을 때 스크립트의 프로퍼티로 초기화하는 데 호출됩니다. Reset 명령을 실행했을 때도 마찬가지입니다. 첫 번째 씬 로드 이 함수는 씬이 시작되면 호출됩니다(씬의 각 오브젝트에 대해 한 번). __ Awake : __이

docs.unity3d.com

반응형

코드 분석 중에 모르는 것이 나와서 정리해두기 위해 포스팅했다.

Destroy

오브젝트(Component,Asset)를 삭제시켜주는 함수다. 가비지가 많이 생성시켜서 반복적으로 불리는 경우(몬스터 등)에서는 사용하지 않고

특정 시간을 주어서 삭제 시간을 정할 수도 있다. Destroy (obj : Object, t : float = 0.0F) 실제 객체 파괴는 항상 현재 Update 루프가 끝나기 전까지 지연되며 렌더링이 되기 전에 파괴된다고 한다.

DestroyImmediate

Destroy 이와 같은데 지연시간을 줄 수가 없다. 큰 차이점은 Update루프가 끝난 후가 아닌 바로 삭제(동일한 프레)된다는 점과 편집기 코드를 작성할 때 사용하고 게임 코드에서는 Destroy를 이용하라고 한다.  주의점으로는 영구적으로 파괴할 수 있다는데..) 

 

언제 DestroyImmediate를 사용해야 하는지는 조금 더 알아봐야겠다.

 

 

https://docs.unity3d.com/ScriptReference/Object.DestroyImmediate.html

반응형

전처리기 / Define


유니티 Define 기능은 각 플랫폼 또는 특정 버전에 코드를 처리할때 유용한 방법이다.



전처리기


멀티플랫폼이 가능한 유니티다 이 말은 하나의 프로젝트로 여러가지 플랫폼으로 빌드가 가능하다는 말이다. 멀티플랫폼이라서 그렇게 간단하게 각기 다른 플래폼 적용이 쉬운것은 아니다. 


안드로이드,IOS,윈도우 각각 플랫폼마다 적용해야 하는 코드가 다를 수 있다. 그러면 플랫폼이 바뀔때마다 스크립트를 각각 별도로 만들어야하고 동적으로 플랫폼을 확인한 후에 컴포넌트를 추가해야 한다.

프로젝트가 커질 수록 작업양은 점점 많아 질 것이다.  



이럴 때 사용하는 것이 전처리기이다.


구문

#if UNITY_EDITOR

Debug.Log("Unity Editor");

#endif


예제)


유니티 에디터에서 각각 다른 플랫폼에서 다른 로그가 나오도록 설정할 수 있는 것이다. 


<유니티에서 지정해놓은 전처리기>



사용자 커스텀 전처리기

유니티가 지정해 놓은 전처리기 말고 사용자가 원하는 전처리기를 만들 수 가 있다.

1.UnityEditor에서 사용자 디파인 셋팅


edit -> Player Settings -> Other Setting -> Scripting Define Symbols




정의하고 싶은 특정 플랫폼의 기호 이름을 입력한다.



Player Settings에는 SHOW_DEBUG_MESSAGES 설정을 했으니


"디파인 테스트2"만 출력된다.






2. using UnityEditor; 필요



특징 컴파일 시 Define여부에 따라 컴파일 자체를 하지 않기 때문에, 실행파일에 코드가 포함되지 않는다.

Define으로 인해 유니티에서 현재 선택되어진 플랫폼이 아닌 다른 플랫폼의 코드들의 스킙트 에러 여부를 바로 확인할 수 가 있다.




학습참고

1) https://docs.unity3d.com/kr/530/Manual/PlatformDependentCompilation.html

2) http://blog.naver.com/PostView.nhn?blogId=hope0510&logNo=220079637714

3) https://bluemeta.tistory.com/12


반응형

 PostProcessing 

(Post Processing Stack은 2018년 이전 버전)


이번 학습목표 최종 결과




라이트를 사용하면 보통 라이트가 비추는곳은 빛이 나기때문에 괜찮은데

정작 빛을 내주는 라이트에서는 빛나지가 않다(후광이 없음)

라이트효과 참고 : https://funfunhanblog.tistory.com/94


이유는 라이팅 시스템이 그작업을 해주지 않기 때문이다.

그 작업을 해보려고 한다.


1) Post Processing 다운로드

유니티 Package Manager에서 다운로드 한다.

그런데 아마 유니티 2018년 이전 버전은 방법이 조금 다르다

Post Processing Stack 

에셋 스토어에서 다운로드 해준다.

다운로드 하면 post processing behavior스크립트를 추가 할 수 있다.

프로젝트창에서 Post - Processing Profile을 생성한다.

모든 셋팅값이 저장되는 곳이다.

생성한 Profile을 아까 추가한 스크립트 profile에 넣어준다. 

그런 뒤 값 세팅

참고 :  https://www.youtube.com/watch?v=o39SjRcA__U (14분 부터)


2) 포스트프로세싱 생성

a) 메인카메라에 Post Process Layer 컴포넌트를 추가한다. 

Layer는 volume이 작동할 레어를 설정해주어야한다. 없다면 추가한다.

Trigger는 This를 눌러준다.


b) Post-processing Profile을 생성한다.

모든 셋팅이 저장되는 곳 이다.


C) Post-processing Profile을 생성한다.

Is Global  : 전역으로 효과를 줄건지 체크

Profile : new를 눌러줘서 새로 만들어준다.

Add effect를 눌러서 추가할 셋팅요소들을 추가 한다. 이번에는 빛자체에서 후광 효과를 주기 위해서 Bloom만 추가해줬다. 

처음에 모든 셋팅설정 값들이 회색으로 나와서 안되는 줄 알았는데 저렇게 체크박스를 체크하니까 값을 넣을 수 있게 활성화가 됐다.


학습참고

1) https://github.com/Unity-Technologies/PostProcessing/wiki/Quick-start

2) https://github.com/Unity-Technologies/PostProcessing/issues/725

3) https://docs.unity3d.com/kr/2017.4/Manual/PostProcessing-Stack.html

4) https://www.youtube.com/watch?v=4Qjm4FQyZuE



반응형


코루틴Coroutine 작동원리



코루틴?



코루틴은 실행을 중지하여 Unity에 제어권을 돌려주고, 그러나 계속할 때 는 다음 프레임에서 중지한 곳부터 실행을 계속할 수 있는 기능. 함수를 호출하면 반환값을 반환하기 전에 실행 완료된다. 즉 , 함수에서 수행되는 작업은 하나의 프레임에서 수행된 다는 것을 의미하고, 함수 호출은 절차적 애니메이션을 포함하거나 시간의 경과 함께 일련의 이벤트에는 사용할 수 없다.

<유니티 공식 메뉴얼>


유니티로 게임 제작을 하다보면 코루틴을 많이 사용하게 된다. 쓰레드의 대해서 정확하게 알지는 못하지만 유니티는 단일 쓰레드로 동작한 다는것은 알고 있었다. 그렇다면 유니티에서 멀티쓰레드처럼 멀티태스킹이 불가능한걸까?  멀티 쓰레드처럼 비슷하게 작동하게 해주는 것이 코루틴이다. 그렇다고 멀티쓰레드가 되는것은 아님


코루틴은 어떻게 작동될까?

코루틴은 IEnumerator를 반환한다. C#의 이터레이터 인터페이스는 프로그래머가 IEnumeraotr를 구현 할 수 있도록 도와준다. 

진입하는 지점을 한 개인 보통 서브루틴 방식과 다르게  진입하는 지점까지 여러 개를 가질 수가 있다. yield return을 통해 그 바로전 시점을 기억하고 다음 호출하게 될떄 그 다음부터 실행이 되는 것이다. 

유니티에서는 대부분 그 시점을 Update에서 체크한다. 


코루틴을 사용할 때 IEnumerator와 같이 사용한다. 이 IEnumerator는 데이터의 목록을 하나씩 넘겨줄 때 사용되는 인터페이스인데, 코루틴은 호출 한 함수와 상호작용하면서 진행되는데 자신을 호출한 함수에 데이터를 하나 넘겨주고 쉬게되는데, 받은 함수에서는 데이터를 받고 처리한 후에 코루틴에게 다음 데이터를 달라고 요청하게 된다. 





(서브 루틴 : 일반적인 함수에서 사용되는 작동개념인데 함수는 시작할 때 진입하는 지점이 저장하고, return구문에 의해서 종료되는 지점을 저장한다. 

Iterator :컬렉션에 대해 사용자 지정 반복을 수행, yield return 문을 사용하고 각 요소를 한 번에 하나씩 반환한다. 이터레이터는 현재 위치를 기억하고 다음 반복에서는 다음 요소를 반환.)






학습 참고:

1). https://m.blog.naver.com/PostView.nhnblogId=captainj&logNo=221102892952&proxyReferer=https%3A%2F%2Fwww.google.com%2F

2). https://seungngil.tistory.com/

3) .http://blog.naver.com/PostView.nhn?blogId=yoohee2018&logNo=220699457038&parentCategoryNo=&categoryNo=&viewDate=&isShowPopularPosts=false&from=postView


반응형

ScriptableObject


스크립팅 가능한 오브젝트

메소드를 실행하는 스크립트가아닌 데이터를 사용하기 위한 스크립트이다.




생성방법

[CreateAssetMenu(fileName = "New HeroData", menuName = "Sword HeroData", order = 2)]

public class test : ScriptableObject

{


}

유니티에서 스크립트를 생성하면 Monobehaviour를 자동으로 상속 받게 되는데 지우고

ScriptableObject를 상속받아온다.


[CreateAssetMenu] : 없어도 되지만 있으면 편함

fileName : 새로 제작하게되면 임시로 생성된다. 

menuName : 유니티 메뉴에 표기되는 이름

order : 메뉴에서 보일 순서

Assets -> Create 보면 방금 생성한 HeroData가 보이게 된다.


SerializeField의 원본 데이터들은 수정되면 안되기 때문에 

데이터 값을 받을 게터를 public으로 추가해준다.

public class test : ScriptableObject

{

    [SerializeField]

    string heroName;

    [SerializeField]

    string description;

    [SerializeField]

    int goldCost;


    public string sName => heroName;

    public string sDesc => description;

    public int    nCoin => goldCost;

}


사용법

데이터 값 입력

ScriptableObject를 받을 코드 작성

public class Scene : MonoBehaviour

{

    public Text m_txtUI;

    public test m_Data;

    void Start()

    {

        m_txtUI.text = string.Format(m_Data.sName + " // " + m_Data.sDesc);

    }

}

Data 매칭 인스펙터 창에서 끌어다 놓는다

실행


데이터를 한 오브젝트나 클래스에서 사용하기에는 괜찮은 것 같다. 데이터가 왔다갔다 하거나 값이 변하는 데이터는 쓰기에 어려울 것 같다.


학습 참고 : https://docs.unity3d.com/kr/current/Manual/class-ScriptableObject.html

https://m.blog.naver.com/yoohee2018/220725032540

반응형


코루틴 Coroutine 


유니티 Update( )함수는 게임의 지속적인 변화를 주거나 게임의 진행되는 매순간 체크(사용자의 입력 등)해야할 경우 사용하게 된다.

하지만 특정행동을 5초 동안 취해야 할 경우,  초당60~80(프레임)번 호출 되는 Update함수 안에서는 제어 하기가 힘들다. 

그리고 플레이하는 디바이스마다 각각 다른 프레임이 나오기 때문에 구현 자체가 더더욱 힘들다.


그래서 C#과 유니티에서는 코루틴이라는 것을 제공한다.

유니티에서 사용할 것이기 때문에 유니티 코루틴을 알아보도록 하자


사용법 

StartCoroutine

void 함수명( ) //Update안에 있는

{

     StartCoroutine( 코루틴 함수 이름( ) );  

}

IEnumerator

    public IEnumerator 코루틴 함수 이름( ) //코루틴 사용

    {

            Debug.log(코루틴 대기);   

 yield return new WaitForFixedUpdate();

            Debug.log(코루틴 완료);

    }

 코드분석

우선 StartCoroutine( ) 괄호안에 코루틴으로 IEnumerator 개채명, 지정한 함수이름을 써준다.

yield라는 것은 반복자의 IEnumerator객체에 값을 전달하거나, 반복의 종료를 알리기 위해 사용한다.

WaitForFixedUpdate( );  다음 FixedUpdate 물리 프레임 전까지 대기

(코루틴 예외 :  함수안에서 만 사용, 알수 없는 이름의 함수(람다)에서는 에러)

코루틴용 데이터엔진이 수행하는 기능
yield return null다음 프레임까지 대기
yield return new WaitForSeconds(float)지정된 초 만큼 대기
yield return new WaitForFixedUpdate()다음 물리 프레임까지 대기
yield return new WaitForEndOfFrame()모든 렌더링작업이 끝날 때까지 대기
yield return StartCoRoutine(string)다른 코루틴이 끝날 때까지 대기
yield return new WWW(string)웹 통신 작업이 끝날 때까지 대기
yield return new AsyncOperation

비동기 작업이 끝날 때까지 대기




참고 : https://docs.unity3d.com/kr/530/Manual/Coroutines.html





반응형

gPlayerPrefs(플레이어프렙스)



키-벨류 방식으로 유니티안에서 간단하게 저장하고 데이터를 불러올수 있다.

getter을 통해 저장하고 setter을 통해 불러온다. 저장가능 용량은 1MB이다.

간단하게 저장할 때 사용한다.(보안x)


사용법 먼저 알아보자


저장하기

PlayerPrefs.SetInt("score", getcoin);

매개 변수안에 key,value를 넣면 된다. 

Setfloat,Setint,Setstring 3가지가있다. 저장하려는 형식의 맞게 사용하면 된다

"score"라는 키값으로  벨류인 getcoin의 값을 저장하고 있다.

(아이템을 먹으면 1씩 증가하는 getcoin)



불러오기 

score = PlayerPrefs.GetInt("score");

불러 올때는 Getter을 사용하는데 score라는 키값으로 getcoin을 불러오는것이다.



적용하기

void Start() {

score = PlayerPrefs.GetInt("score");

getCoin();

}


void OnApplicationQuit() //종료 콜백함수

{

PlayerPrefs.SetInt("score", getcoin);

}

이런식으로 시작할 때 저장한 값을 불러오고 종료할때 값을 저장했다.


삭제하기

유니티를 꺼도 삭제되지 않는다 그렇기 때문에 키워드를 통해 지워줘야한다.

PlayerPrefs.DeleteAll

PlayerPrefs.DeleteKey("키이름")


https://docs.unity3d.com/kr/530/ScriptReference/PlayerPrefs.html




반응형

Camera.ScreenPointToRay


카메라로 부터의 스크린의 점을 통해 레이를 반환합니다.

스크린공간은 픽셀로 정의되며.

픽셀단위

1번 : 왼쪽 하단의 화면이 (0,0)

2번: 오른쪽 상단이 (pixelWidth,pixelHeight)


if (Input.GetButtonDown("0"))

{


Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

RaycastHit hit;

if (Physics.Raycast(ray, out hit, Mathf.Infinity))

{

print("raycast hit!");

Debug.DrawRay(ray.origin, ray.direction * 20, Color.red, 5f);

Debug.Log(hit.point);

}

}




Debug.Ray를 통해 어느부분을 클릭했는지 씬뷰에서 확인이 가능하다.

hit.point를 통해 스크린상 좌표값을 얻어 올 수 있다.

반응형

Raycast


Physics.Raycast

어떤 콜라이더와 레이가 충돌했으면 true, 아니면 false.


Debug.DrawRay 체크 : 거리와 위치를 디버깅 할 수 있다.(유니티 씬장면에서만 나옴)

Debug.DrawRay(transform.position, transform.forward * 8, Color.red);


(위 scene, 아래 game)


충돌한 오브젝트 반환하기

       RaycastHit hit;

       if (Physics.Raycast(transform.position, transform.forward, out hit, 8))

       { //광선을 쏴서 충돌한 게임 오브젝트를 레이캐스트 변수에 저장처리한다.

           Debug.Log(hit.collider.gameObject.name);

       } //광선이 충동한 게임 오브젝트의 이름을 콘솔창에 출력한다.

콘솔창을 보면 ray에 닿은 오브젝트를 확인 할 수 있다.



중첩되는 오브젝트일경우 Physics.RaycastAll

RaycastHit[] hits; //Raycast데이터 저장용 배열 설정

       hits = Physics.RaycastAll(transform.position, transform.forward, 8.0f);


       for(int i=0; i<hits.Length; i++)

       {

           RaycastHit hit = hits[i];

           Debug.Log(hit.collider.gameObject.name);

       }


Raycast데이터 저장용 배열을 사용한다.

정해진 길이만큼 통과한 오브젝트들의 이름을 반환한다.

반응형

오브젝트 찾기



이름으로 찾기



이름으로 오브젝트를 찾는법

GameObject.Find("찾고자 하는 오브젝 이름");


그런데 오브젝트가 비활성화 되어있다면 이방법이 불가능합니다.

부모오브젝트를 찾은 다음에 자식오브젝트를 찾아야합니다.


비활성화 된 오브젝트 찾는법


GameObject.Find("부모 오브젝트 이름").transform.Find("자식 오브젝트이름").gameObject;



인덱서로 찾는법(첫 번째가 0) 

GameObject.Find("Panel").transform.GetChild(0).gameObject;



태그로 찾기


GameObject.FindWithTag("태그명");



위 방법들은 유니티 하이라이키상에 있는 오브젝트를 찾을 수 있다.

사실 게임로직에서는 위에 있는 Find로 특정 오브젝트를 찾는 경우는 드물다. 특히 실시간으로 계속해서 찾는 경우는 더더욱 쓰지않는다. 하이라키상에서 나와있는 모든 오브젝트를 모두 검사해야하기 때문에 그만큼 시간도 오래걸리고 비용도 들기 때문이다. 

반응형

OnTrigger , OnCollision 비교하기

 

Collider

유니티에서 충돌체크를 하기 위한

필요한 컴포넌트이다.

 

3D오브젝트를 생성하면 Collider가 자동적으로

추가 되어있다.

 

먼저 Trigger에 대해 살펴보자

1) void OnTriggerEnter(Collider other) : Trigger에 들어갔을 때

2) void OnTriggerStay(Collider other) : Trigger안에 있을때

3) void OnTriggerExit(Collider other) : Trigger를 벗어 날때

 

 

1) OnTriggerEnter


    void OnTriggerEnter(Collider other) 

{

if (other.gameObject.CompareTag ("Pick Up"))

{

other.gameObject.SetActive (false);

 

count = count + 1;

           

            SetCountText ();

            Debug.Log(count);

}

코드는 Roll a Ball 플레이 스크립트

Collider가 닿게 되면 아래 코드가 실행된다.

 

 

흰색 볼에 스크립트를 추가 하였다. 그리고 노란색 Cube에 닿을때 마다

왼쪽 상단에 Count 값이 증가되고 있는것을 볼수 있다.

 

 

2) OnTriggerStay

우선 // other.gameObject.SetActive (false); 

위 코드면 큐브가 사라진다.

Collider가 닿은 상태를 유지 하는 동안을 보기위해

주석 처리하고 실행했다.

 

Count가 닿는 동안 계속 증가하는것을 볼 수 있다.

그렇다면 Exit도 충분히 예상 가능하다.

 

 

3) OnTriggerExit

 

노란색 큐브를 닿는 순간에는 아무일이 일어나지 않지만

큐브를 지나쳐가는(벗어나는) 순간 Count가 올라간다.

 

OnTrigger를 알아봤는데 꼭 설정해 줘야하는것들이 있다.

노란색큐브와 흰색공에는 반드시 충동체크를 할수 있는 Collider가 있어야한다.

 

그리고 두 오브젝트중 하나는 Collider에 is Trigget에 체크가 되어있어야한다.

위 게임같은 경우에는 큐브에 체크가 되어있다. 흰색공에 체크 되어있지 않는 

이유는 is Trigger 가 체크가 되면 흰공에는 Rigidbody에 무게 값을 갖고있기 때문에

땅을 통과해 밑으로 사라져버린다.

 

 (하지만 여기서는 Cube에도 Rigidbody에 UseGravity에 체크되어있는데 땅으로 떨어지지 않고있다. Is Kinematic를 체크 하고있기 때문)

 

 

 

OnCollsion

void OnCollisionEnter(Collision other) : Collision에 들어 갔을 때

void OnCollisionStay(Collision other) : Collision과 충돌하고 있는 중

void OnCollisionExit(Collision other) : Collision과 충동에서 벗어 났을 때

 

 

Trigger와 함수의 기능은 똑같다

OnTrigger : 물리 연산 안함, 관통 가능, Collision 보다 연산이 적어서 효율적

OnCollision : 물리 연산을 통해 충돌 처리, 관통 X, 많이 사용하면 부하?.


여기서 주의할 점은 충돌 할 오브젝트들이 Rigidbody를 갖고 있다면오브젝트 모두 isTrigger가 언체크 되어있어야 하고 또,둘중 한 오브젝트는 Is Kinematic가 언체크 되어 있어야 한다.

 

 

반응형

Roll a Ball



Materials 적용하기

Asset에서 빈Materials을 생성한다.

그리고, Texture파일을 빈Materials에 Albedo에 끌어다 놓는다. 


Physic Material

Materials 에 반동을 주거나 마찰력을 주기 위한 Materials 

Component -> Physic Material 생성한다.



Physic Material 인스펙터창을 살펴보자

Dynamic Friction : 이미 이동중일 때 마찰

Static Friction : 정지시 마찰

Bounciness : 반동방식


나는 벽에다 Physic Material를 추가 하고 Bounciness값을 0.5주었다.



그랬더니 ~

볼을 벽에 부딪히면 전과 다르게 튕겨 나온다.

(캐릭터 움직임에는 translate으로 위치값을 변경해주는 방법과

rigdbody를 통해 물리적힘을 줘서 물체를 움직이는 방법이있는데

이 게임은 rb.AddForce (movement * speed); 로 물체에 힘을 줘서 움직이게 하고있다.)





코드분석






코드분석 : PlayerControllers

public으로 변수를 할당하면 유니티 인스펙터창에서 보인다. 변경가능 (값 적용 우선순위 : 인스펙터 > 소스코드창)

speed : 스피드 값

Text CountText; 현재 점수를 불러올 UI 텍스트

Win Text : 승리시 띄울 UI텍스트


void Start ()

{

rb = GetComponent<Rigidbody>();


count = 0;

SetCountText ();

winText.text = "";

}

주요코드

rb = GetComponent<Rigidbody>();

컴포넌트 Rigidbody를 가져와 변수 rb로 정한다.


void FixedUpdate ()

{

float moveHorizontal = Input.GetAxis ("Horizontal");

float moveVertical = Input.GetAxis ("Vertical");


Vector3 movement = new Vector3 (moveHorizontal, 0.0f, moveVertical);


rb.AddForce (movement * speed);

}

주요코드

rb.AddForce (movement * speed);

Rigidbody를 물리적 힘을 가해 플레이어를 이동시킨다.



void OnTriggerEnter(Collider other)

{

if (other.gameObject.CompareTag ("Pick Up"))

{

other.gameObject.SetActive (false);


count = count + 1;


SetCountText ();

}

}

주요 키워드

CompareTag : 해당하는 태그를 찾는다.

SetActive : 컴포넌트에 토글? 켜고,끄기

OnTriggerEnter: Collider가 다른 트리거 이벤트에 침입했을 때 호출

(지금 위 코드에서는 pick up 태그가 붙은 오브젝트(노란상자)에 Collider가 닿으면 count를 1증가한다.)




반응형

Quaternion


쿼터니언이은 회전을 표현하기 위해 사용된다.

복잡한 수를 기반하고 있어 직관적으로 이해하기 쉽지 않다.
그래서 대부분 기존의 회전축을 취하고(즉, Transform으로 부터) 새 회전을 생성하기 위해 사용한다.



  •  Quaternion.LookRotation : 지정된 upwards와 upwards 방향들과 함께 rotation을 생성합니다.

  •  Quaternion.Angle :두개의 roation b와 b 사이의 각도를 반환합니다.

  •  Quaternion.Euler : z축 주위로 z, x축 주위로 x, y축 주위로 y 각도만큼 회전한(순서대로) Rotation을 반환합니다.

  •  Quaternion.Slerp : /from/과 /to/사이를 /t/로 구형보간 합니다

  •  Quaternion.FromToRotation:/fromDirection/에서 /toDirection/으로 회전한 rotation을 생성합니다.

  • Quaternion.identity.: 쿼터니언은 "회전 없음"을 의미합니다. 오브젝트는 완벽하게 월드 좌표 축 또는 부모의 축으로 정렬



쉽게 정리하면 transform.rotation에 대입하기 위한 변수 타입이라고 생각하면 쉽다.

Quaternion.Euler(x: float , y: float, z: float) :오일러는 절대각도를 의미.


ex)

현재 transform.Rotate 값이 (0,10,0) 이다


1) transform.Rotate(0,30,0) (더하기 개념)

=>Rotation에 x,y,z가 0,40,0 //현재 상태에서 증가


2) (transform.rotation=Quaternion.Eular(0,30,0))

=> Rotation에 x,y,z가 0,30,0


Eular는 파라미터로 들어온 벡터의 오일러 값을 쿼터니언으로 바꿔주는 함수이다.




반응형




열겨형 Enum 사용법




const 대신 사용하는데 유니티에서 보통 오브젝트의 상태를 구분하여

열거형 타입의 변수를 선언및 할당하여 그 값의 맞는 액션을 취하 도록 한다.


scriptA

public enum eMove_Type { eMove_None, eMove_Normal, eMove_Dash }

public class MoveObj : MonoBehaviour {


   Vector3 vDestPos = new Vector3(7.0f, 1.5f, 1.0f);

   Vector3 vDir;


   public float mfSpeed = 1.5f;

   eMove_Type memove_Type = eMove_Type.eMove_None;



scriptB

eMove_Type mpreType = eMove_Type.eMove_Normal;



반응형

월드 좌표

-오브젝트의 위치를 나타내는 좌표계로, 화면의 중심을 원점(0,0,0)으로 하는 3차원 상대좌표계 월드 좌표계는 게임 화면을 투영하는 카메라의 위치와 회전 상태에 따라 달라지므로 화면의 중심이 원점이 되는것은 아니다.

쉽게 얘기하면

월드를 기준으로 태양이 우주를 중심으로 0.0.0에 위치라고 하면 내위치를 말하는 것이 월드 좌표다. 


로컬 좌표

자신의 위치를 중심으로 생각하고 각각의 그 오브젝트의 위치에서 어디있는지 계산하는것이다.

만약 부모 객체가 있다면 부모객체의 좌표와의 거리를 나타낸다. 상대좌표라고도 한다.


스크린 좌표

-단말기의 화면 좌표계로, 화면의 왼쪽 아래를 원점으로 하는 평면 절대좌표계 마우스 클릭이나 터치는 스크린 좌표계를 이용해서 처리한다. 카메라의 위치나 각도와 상관없이 일정


뷰 포트 좌표

  • 화면에 글자나 2D이미지를 표시하기 위한 좌표계로, 화면의 왼쪽 아래를 (0,0)오른쪽 위를(1,1)로 하는 평면 상대 좌표계이다.


출처 :​ http://hyunity3d.tistory.com/m/post/368

반응형

+ Recent posts