본문 바로가기

게임 프로그래밍/unity

유니티 튜토리얼 1


현재 실행 중인 게임 오브젝트에 포함된 컴포넌트에 액세스 할 때 : GetComponent 메소드

MyScript ms = GetComponent<MyScript>() 형태로 가져올 때에 해당 게임객체에 해당 컴포넌트가 존재하는 경우 스크립트의 순서와 관계없이 액세스가 가능한데, 이는 컴포넌트의 생성은 게임객체 생성 시에 일괄적으로 수행되고 난 다음에 안전하게 수행되는 듯 보인다. 물론 해당 컴포넌트가 객체에 포함되어 있지 않으면 널포인터예외가 발생함


게임 내의 어떠한 오브젝트를 찾을 때 : Tag, Layer, GetGameObject, .gameObject 활용

GameObject.find("name") 은 아주 편하겠지만, 너무많은 게임객체 상에서 성능저하가 예상되므로, 항상 Tag를 사용하는 습관을 들이자. Layer는 주로, 씬 상에서의 게임객체 간에 필터링 용도로 사용되며, Tag는 스크립트 컴포넌트 상에서 주로 사용된다. 그래서인지 Layer는 32개의 개수제한과 8개의 reserved layer가 존재하므로, 24개만 사용가능하다. 암튼 객체 찾을 때에는 Tag를 쓰자. 다만, 부모자식 관계를 맺어서 활용하는 경우가 많기 때문에 대부분 Child/Parent GetGameObject 함수를 거의 쓰게 되지만, 결국 그 관계가 깨지면, 코드를 수정해야 하는 불편함이 있는데, 이는 초기 설계상 혹은 Convention으로 정의해두는 편이 좋겠다.


물론 가장 좋은 방법은, 게임오브젝트는 컴포넌트를 통해서 .gameObjecct 를 쓰는 것

컴포넌트는 쉽게 액세스가 가능하므로, 아래와 같이 쉽게 찾을 수도 있다

cube = GameObject.Find ("Spinner");

cube = GameObject.FindObjectOfType<Spinner>().gameObject;

cube = GetComponentInChildren<Spinner> ().gameObject;


키보드 입력은 Input 클래스를 통해 받는데 GetKeyDown 은 한 번 누르는 것, GetKey는 계속 누르고 있는 이벤트를 말한다.


같은 회전이라도 아래와 같이 여러가지 방식으로 구현이 가능하다.

transform.rotation *= Quaternion.Euler(new Vector3(0f, 0f, Time.deltaTime));

transform.Rotate (new Vector3 (0f, 0f, Time.deltaTime));

transform.Rotate (Vector3.forward * Time.deltaTime);



스크립트의 호출 순서에 유의 할 것

이런 저런 말들은 많은데...


기본적인 설정 하에서는 아래의 순서를 따름.

  1. Awake
  2. OnEnable
  3. OnLevelWasLoaded (only on scene changes)
  4. Start

스크립트가 InActive 상태(Unchecked)인 경우에는 아래와 같음

  1. OnLevelWasLoaded // is now called first, before Awake()! (only on scene changes) 
  2. Awake
  3. [OnEnable()/Start() are not executed until the script is actually enabled]
여러 객체가 존재하는 경우 더욱 신비로운 현상이 나타나는데, 객체를 생성한 역순으로 Awake, OnEnable 을 쌍으로 수행된 후, Start는 따로
  1. Awake() of ObjectC
  2. OnEnable() of ObjectC
  3. Awake() of ObjectB
  4. OnEnable() of ObjectB
  5. Awake() of ObjectA
  6. OnEnable() of ObjectA
  7. Start() of ObjectC
  8. Start() of ObjectB
  9. Start() of ObjectA
추가로 Script Execution Order 를 A, B 순으로 지정하면 그나마 예상한 순서대로 나온다.
  1. Awake() of Type A, instance 1
  2. OnEnable() of Type A, instance 1
  3. Awake() of Type A, instance 2 // order of instances cannot be influenced
  4. OnEnable() of Type A, instance 2 // order of instances cannot be influenced
  5. Awake() of Type B
  6. OnEnable() of Type B
  7. OnLevelWasLoaded() of Type ? // order cannot be influenced
  8. OnLevelWasLoaded() of Type ? // order cannot be influenced
  9. Start() of Type A
  10. Start() of Type B
결론은 스크립트가 Active 한 상태의 스크립트 컴포넌트에 한해서는 Awake, OnEnable Start 순서는 보장 받지만, 객체 간의 Awake 순의 순서는 보장받지 못한다. 결국 Awake 와 OnEnable 은 쌍으로 동작하므로 Awake 와 Script Order 만 고려하는 것이 정신건강에 좋겠다.


Awake, Start, Update, LastUpdate, FixedUpdate 함수 차이점

 Start 함수의 차이는 스크립트 컴포넌트가 Enabled 한 상태에서만 호출되며, Awake 함수는 다른 어떤 Awake, OnEnable 함수보다 늦게 호출되기 때문에 초기화 작업에는 Start 함수 보다는 Awake 함수가 더 좋겠다. 다만, Enabled 되지 않은 상태에서도 호출되므로 유의할 것.


 Update 함수는 매 프레임 마다 호출되고, LastUpdate는 마지막 Update 함수 호출 이후에 호출되는 함수이므로, Follow Camera 가 존재하는 경우 이 함수에 넣으면 좋다고 한다.


 FixedUpdate 경우 고정된 프레임 비율마다 호출되는 함수인데, rigidbody에 force를 가할 때에 일정 량의 힘을 가하고 싶다면, Update 함수 대신 FixedUpdate 함수를 사용해야만, 일정한 힘을 가하는 데에 성공할 수 있다고 얘기하고 있다.


Last/Fixed Update 함수는 직접 적용해보지 않아서 잘 모르겠지만, 글의 내용을 보아서는 대충 이해할 수 있을 듯.


'게임 프로그래밍 > unity' 카테고리의 다른 글

3D 러닝게임 리뷰  (0) 2015.03.14
선녀와 나무꾼  (0) 2015.03.09
Unity를 통한 게임개발 시작  (0) 2014.12.18