Unity에 작업을 할 때, 스크립트를 새로 생성하면 기본적으로 생성되는 두 함수가 있다.
바로 Start와 Update, 각각 처음에 한 번, 프레임 마다 한 번 씩 호출되는 함수인데 다들 이 둘의 기능은 알 것이다.
하지만 이 둘은 유일한 함수가 아니다.
그 중 Start 함수와 비슷한 기능을 하는 Awake가 있다.
둘의 차이점은?
유니티의 함수 호출 순서이다.
그림을 보면 Awake가 Start보다 먼저 호출되는 것을 알 수 있다.
그 외로, Start는 비활성화 상태에서는 호출되지 않는다는 점 빼고는 거의 유사한 기능을 한다.
그래서 Start? Awake?
// Start is called before the first frame update
void Start()
{
}
스크립트를 처음 생성하면 볼 수 있는 코드이다.
아마 초기화 코드나 객체의 참조 등의 코드를 여기에 적게 될 것이다.
하지만 Awake가 더 유용할 수 있다.
void Awake()
{
}
Awake는 스크립트가 처음 로드될 때 또는 스크립트가 연결된 객체가 인스턴스화될 때 호출된다.
각 스크립트에서 한 번만 호출되며 다른 개채가 초기화된 후에만 호출된다.
그래서 Awake에서 다른 객체와 스크립트의 참조가 일어나는게 안전할 수 있다.
하지만..
아마 누군가는 이런 에러를 경험한 적이 있을 것이다.
public class Object_A : MonoBehaviour
{
Object_B objectB;
private void Awake()
{
Debug.Log("오브젝트A의 Awake함수 실행");
objectB = GameObject.FindWithTag("ObjectB").GetComponent<Object_B>();
Debug.Log(objectB.reference.message);
}
}
public class Object_B : MonoBehaviour
{
public Reference reference;
private void Awake()
{
Debug.Log("오브젝트B의 Awake함수 실행");
reference = GetComponent<Reference>();
}
}
이 코드를 보면 오브젝트A에서 오브젝트B의 reference에 참조하려고 하고 있다.
reference는 Awake에서 초기화 했으니까 작동해야 하지 않나? 싶지만 에러가 발생한다.
- reference가 초기화 되지 않았다
이유는 당연하게도 아직 reference를 초기화 시켜주는 Object_B의 Awake함수가 실행되지 않았기 때문이다.
로그를 살펴보면 Object_A 의 Awake함수가 Object_B 의 Awake보다 먼저 호출 된 것을 볼 수 있다.
어떤 오브젝트의 Awake가 먼저 실행되는지 알 수 없으니 이런 식의 참조는 바람직하지 못하다고 할 수 있다.
그럼 어떻게?
Awake와 Start 함수를 동시에 사용하자.
Awake에서 초기화를 진행하고 Start에서 참조를 진행하면 된다.
물론 Start는 오브젝트가 활성화 되어있을 때만 실행된다는 것을 기억해야 한다.
또는 Start 함수를 Couroutine으로 호출하면 된다.
private IEnumerator Start()
{
yield return new WaitForSeconds(1); // 1초 기다림
// 코드...
}
void 를 IEnumerator로 교체해서 사용하면 된다.
하지만 이 방법은 별로 추천하지 않는다.
결론
Awake와 Start를 동시에 사용해서 Awake에서는 초기화 Start에서는 참조를 하자.
'게임 개발' 카테고리의 다른 글
Unity Engine 내에서 오브젝트 중심으로 Pivot 옮기 (0) | 2024.05.26 |
---|---|
LateUpdate가 중요한 이유 (0) | 2024.04.25 |
BoxCollider does not support negative scale or size. (0) | 2024.04.22 |
UnityEngine.Assertions 을 이용한 에러 검출 (0) | 2024.04.21 |