
위 이미지는 Order of execution for event functions (이벤트 메서드 순서)의 플로우차트 일부분으로,
이번 포스트는 Initialization 파트를 다루고 있습니다.
Awake OnEnable Start
MonoBehaviour에서 상속받아 사용할 수 있는 클래스 메서드로,
인스턴스의 초기화와 시작시 행동을 관리할 때 사용합니다
순서는 Awake → OnEnable → Start 입니다.
Awake()
새 오브젝의 인스턴스가 생성될 때, 첫빠따로 호출되는 메서드입니다.
항상 Start 함수 이전에 호출 됩니다.
만약 GameObject가 시작했는데 비활성화 상태일 경우엔, 활성화될 때까지 Awake()는 호출되지 않습니다.
게임이 시작될 때 호출하므로, 여러 객체에서의 Awake() 호출은 (isn't Manually) 간혹 주의가 필요한데,
A 객체에서는 B 객체의 Awake()가 이미 호출된 상태를 가정해서는 안된다고 합니다.
필요하다면 Start로 참조를 수행하는 것이 안전합니다.
(하지만, 공식문서에선 RunTime에서는 이를 강제할 수 없다고 하네요)
추가로 일시적인 필요로 리소스를 Awake에서 호출할 경우, 메모리에 계속 남기 때문에,
적절한 때 해제를 해 줘야합니다. (Destroy(), Resources.UnloadUnusedAssets() 등)
void Awake() {
DavidsComponent = GetComponent<DavidsComponent>(); // 참조 설정 등
}
OnEnable()
말 그대로 객체가 활성화될때 호출되는 함수이며, 반대 개념은 OnDisable() 입니다.
인스턴스가 활성활 될 때마다 호출되는 메서드이기에 코드를 가볍게 작성하도록 신경써야 합니다.
게임 런타임 중, 오브젝트가 활성화 될 때, 어떤 이벤트가 발생하면 반응하도록 리스너 Subscribe을 해둡니다.
void OnEnable() {
EventManager.OnWorkHard += Respond; // 리스너 subscribe (등록)
StartCoroutine(AnythingWahtUwant());
}
void OnDisable() {
EventManager.OnWorkHard -= Respond; // 리스너 해제
StopAllCoroutines();
}
Event Listener 등록과 해제 (OnDisable()해주지 않을시 누수 현상 발생 가능) 를 해당 메서드에서 처리하며,
혹은 코루틴과 같은 주기 작업에 관해서도 OnEnable() 에서 관리해줄 수 있습니다.
void OnEnable() {
StartCoroutine(WorkRepeatedly());
}
IEnumerator WorkRepeatedly() {
while (true) {
Debug.Log("어쩌구 저쩌구 바쁘다 바빠");
yield return new WaitForSeconds(10f);
}
}
void OnDisable() {
StopAllCoroutines(); // 코루틴 멈추기
}
게임 실행 중 UI 상태 변경 등에도 사용한다고 합니다.
Start()
Update()의 첫 프레임이 호출되기 전에, 한번 호출됩니다.
Awake()와 마찬가지로, Start() 메서드에서도 초기화를 담당합니다.
Awake()와 비교하면 아래와 같습니다.
| Awake() | Start() | |
| 초기화 | 컴포넌트 초기화 | 간단한 private 필즈 값 초기화 |
| 예시 | GetComponent<>()... | 게임 시작에 필요한 로직 구성 → ex) 플레이어 위치, 애니메이션 상태, 기타 미디어 트리거 상태 등 |
| 다른 객체 Awake 관계 | 다른 스크립트의 Awake()가 호출되기 전이라는 걸 보장할 수 없음 | 다른 객체의 Awake()에서 설정된 값에 의존하는 초기화 작업 가능, (즉, 다른 객체의 컴포넌트나 필드 참조 가능) |
| 호출 시점 | 비활성화 상태여도 호출 | 활성화 상태일 때만 |
주의 사항으로 예시 코드 하나 보고 마치겠습니다.
// GameManager.cs
public class GameManager : MonoBehaviour {
public string message;
void Awake() {
message = "Hello from Awake!";
}
}
// UIManager.cs
public class UIManager : MonoBehaviour {
void Start() {
Debug.Log(FindObjectOfType<GameManager>().message); // 아주 바람직 해용!
}
}
위 처럼 Start() 메서드가 다른 객체의 Awake() 참조를 문제없이 하였습니다.
하지만, 아래와 같이 작성하는 것은 위험합니다.
// UIManager.cs
public class UIManager : MonoBehaviour {
void Awake() {
Debug.Log(FindObjectOfType<GameManager>().message); // 메세지가 null일 가능성 있음
}
}
위에서 말했 듯이, 여러 객체가 Awake() 메서드는 순서가 보장이 되지 않습니다.
저 같은 경우는 Awake()와 Start() 메서드의 차이가 단순 시작 초기화 프레임 뿐인 줄 알고,
명확한 구분없이 사용했었어요.
혹시나 저와 같은 실수가 있었던 분들 께서는, 이제부터라도 초기화 메서드들의 구분을 명확히 하여,
예쁘고 정갈한 코드를 작성하실 수 있기를 바라요. 감사합니다.
그럼 오늘도 좋은 하루 되시길 바라요~ *⋆꒰ঌ(⁎ᴗ͈ˬᴗ͈⁎)໒꒱⋆*
'- Unity > let us all UNITE !' 카테고리의 다른 글
| [Unity] Addressable #1 (Local) (0) | 2025.06.19 |
|---|---|
| [Unity] Getting started with UniRX ( Observer Pattern ) (1) | 2025.05.22 |
| [Unity] Update FixedUpdate LateUpdate (0) | 2025.05.16 |
| [Unity] InputSystem 인풋시스템 (1) | 2025.04.25 |
| [Unity] 터치, 입력(Input) 시스템 정리 (1) | 2025.04.25 |