Post

생명주기 [2]

Awake(), OnEnable(), OnDisable(), Start()

생명주기 [2]

Awake()


특징

1. 반드시 Start 함수 전에 호출된다.

SceneEmpty 오브젝트를 생성 후, 아래의 스크립트를 컴포넌트로 추가한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
using UnityEngine;

public class Test : MonoBehaviour
{
    void Awake()
    {
        Debug.Log("Awake");
    }

    void OnEnable()
    {
        Debug.Log("OnEnable");
    }

    void Start()
    {
        Debug.Log("Start");
    }
}


게임을 실행시키면, 아래의 사진과 같이 순서대로 호출되는 것을 볼 수 있다.

img


2. Scene 에 있는 모든 객체에 대해 호출된다.

게임 오브젝트 4 개를 배치한 뒤, 위의 Test.cs 스크립트를 컴포넌트로 추가한다.

img


게임을 실행시키면, 아래의 사진과 같이 Awake 가 4번 호출되는 모습을 볼 수 있다.

img


단, 유니티에서는 같은 씬에 있는 여러 오브젝트들의 Awake 호출 순서를 보장하지 않는다.

순서를 제어하고 싶다면 Edit → Project Settings → Script Execution Order 에서 설정할 수 있다.

하지만 이것은 스크립트 단위이고 오브젝트 단위가 아니라서, 같은 스크립트를 여러 오브젝트에 붙였을 땐 제어가 어렵다.


3. 함수는 게임이 실행된 이후 스크립트 당 최초 1 회만 호출된다.

Awake 함수는 게임 오브젝트가 파괴되고 재생성 하는것이 아닌 이상 단 한번만 호출된다.

아래의 사진을 보면, 스크립트를 껐다가 켜는 행위를 반복해도 호출이 되지않는 모습을 볼 수 있다.

img Check Console


4. 게임 오브젝트가 활성화 되어있다면, Awake 함수는 반드시 호출된다.

다르게 말해서, 스크립트가 활성화되어 있지 않더라도 Awake 는 호출된다.

아래와 같이 스크립트를 비활성화 한다.

img


게임을 실행하면, 스크립트가 꺼져있음에도 Awake 함수가 호출된 것을 확인할 수 있다.

img


Caution

  • Awake 함수 내에 많은 연산을 하게 되면 게임 시작 전 로딩시간이 길어지게 된다.
    그래서 최대한 Awake 내의 함수는 경량화 시키는 것이 좋다.
  • 여러 게임 오브젝트에서 Awake 함수가 호출하는 경우는, 호출 순서는 보장받을 수 없다.
    그래서 A 객체 에서 B 객체Awake 함수를 호출된 상태로 가정해선 안된다.
  • Awake 는 해당 게임 오브젝트가 파괴 되기 전까진 메모리상에서 계속 남아있게 된다.
    그래서 Awake 내에서 텍스처나 사운드 등을 불러왔을 때, 리소스들은 적절한 시점에서 해제되어야 한다.
  • 만약 두개의 게임 오브젝트가 서로를 참조해야한다면, 둘 중 하나는 Start 함수 내에서 참조를 실행하는 것이 안전하다.


Tip

  • 객체의 컴포넌트를 참조할 경우엔 Awake 에서 참조하는 것이 일반적이다.
  • 싱글톤 패턴을 적용할 때 보통 Awake 함수에서 로직을 처리한다.


OnEnable()


특징

OnEnable 함수는 스크립트, 혹은 게임 오브젝트가 활성화 될 때 마다 호출된다.

아래의 사진을 보면 체크박스를 껐다 켤 때 마다 OnEnable 의 호출횟수가 늘어나는 것을 볼 수 있다.

img Check Console


Caution

  • OnEnableStart 함수 전에 호출되므로, Start 함수가 인지하기 전의 기능들을 호출해선 안된다.
  • OnEnable 은 게임 오브젝트, 혹은 스크립트 컴포넌트가 활성화 될 때 마다 호출되므로,
    무거운 연산 혹은 긴 시간을 사용하는 알고리즘 또는 로직을 포함시키면 게임 성능에 악영향을 끼칠 수 있다.
  • OnEnable 내의 로직은 최대한 간결하게 유지하도록 신경쓰는 것이 좋다. 불필요한 연산 및 호출 최소화


Tip

  • 이벤트 리스너를 등록하고 해제하는 패턴으로 활용할 수 있다.
  • 필요한 리소스를 동적으로 불러오고, OnDisable 로 해당 리소스를 해제하는 패턴으로
    메모리 관리 및 성능 최적화를 할 수 있다.


OnDisable()


특징

OnDisable 함수는 OnEnable 과 반대로, 스크립트나 게임 오브젝트가 비활성화 됐을 때 호출된다.

게임 오브젝트가 파괴 되었을 때도 실행된다.

생명주기를 보면 OnDisable 이후에 바로 OnDestroy 가 호출되는 것을 볼 수 있다.

조금 더 상세하게 말하자면 비활성화가 되는 과정 이 있어야 실행이 되는 것이다.

스크립트가 처음부터 비활성화 인 상태에서는 OnDisable 이 호출되지 않는다.


TestCase 1

  1. 게임 오브젝트 및 스크립트 컴포넌트가 활성화 되어있는 상태로 게임실행.
  2. 스크립트 컴포넌트를 비활성화 함 → 예상대로 OnDisable 함수 호출됨.
  3. 이 상태에서 게임오브젝트도 비활성화 하면 호출되는가? → OnDisable 호출 안됨.

TestCase 2

  1. 게임 오브젝트 및 스크립트 컴포넌트가 활성화 되어있는 상태로 게임실행.
  2. 스크립트 컴포넌트를 비활성화 함 → OnDisable 함수 호출됨.
  3. 게임 오브젝트 비활성화 → 위에서 진행한 TestCase 1 과 똑같이 호출 안됨.
  4. 게임 오브젝트를 다시 활성화.
  5. 게임 오브젝트를 다시 비활성화 → 이때는 OnDisable 이 호출되는가?
    → 안됨. 활성화 상태의 스크립트 컴포넌트가 비활성화 될 때 호출되는 것.


Start()


특징

  • Start 함수는 AwakeOnEnable 함수가 호출 된 뒤에 이루어진다.
  • Scene 에 배치된 **모든 객체의 Awake 함수와 OnEnable 함수가호출 되고 나서, Start 함수가 호출된다.
  • 컴포넌트 활성화 된 순간을 기준으로, 첫번째 프레임가 업데이트 전에 호출된다.
  • Awake 와 마찬가지로 객체에 대해서 최초 1 회만 호출되기 때문에, 객체의 초기화 작업에 주로 사용된다.


Awake VS Start

항목 Awake Start
호출 조건 게임 오브젝트가 활성화 상태이면,
스크립트가 비활성이어도 호출됨
게임 오브젝트가 활성화
+ 스크립트도 활성화 상태일 때만 호출됨
호출 시점 오브젝트 생성 직후, 모든 Awake가 먼저 호출됨 모든 Awake 호출 후, 프레임 시작 시점에 호출
주요 용도 자기 자신의 컴포넌트 초기화 및 참조 다른 객체나 외부 리소스에 대한 참조
싱글톤 구현 Awake에서 구현하는 것이 일반적 다른 객체에서 먼저 접근 시 문제 생길 수 있음
상호 참조 안정성 불안정 상대적으로 안정적


Tip

  • 보통 게임 로직의 초기세팅을 담당한다.
    • ex) 캐릭터의 체력, 스탯, 초기 위치, 스테이지의 시작상태, 초기 애니메이션 등


Reference