[Unity] 유니티의 생명주기 (Lifecycle)

Donghee·2024년 3월 7일
0
post-thumbnail

생명주기(Lifecycle)란?

유니티 스크립트가 실행되면 순차적으로 이벤트 함수가 호출이 된다. 객체가 생성되어 활성화되고, 업데이트하고, 파괴되고, 이러한 과정이 마치 생명이 살아가는 과정처럼 느껴져 생명주기(Lifecycle)라고 부른다. 굳이 생명주기를 다 외우고 있을 필요는 없다고 느끼지만, 전체적인 흐름을 짚고 가서 나쁠 건 없다고 본다.

이벤트 함수의 실행 순서

씬이 처음 로드될 때

Awake

이 함수는 항상 Start 함수 전에 호출되며, 프리팹이 인스턴스화(프리팹의 씬 오브젝트화)된 직후에도 호출된다. 시작 중에 게임 오브젝트가 비활성화 상태라면,오브젝트가 활성화될 때까지 Awake는 호출되지 않는다.

OnEnable

이 함수는 오브젝트가 활성화된 직후 호출된다. MonoBehaviour 인스턴스가 생성될 때 발생한다. 모든 스크립트의 Awake 및 OnEnable 함수는 Start, Update 등 이 호출되기 전에 호출된다. 물론 게임플레이 중에 오브젝트를 인스턴스화할 때는 이 기능이 적용되지 않는다.

씬의 각 오브젝트들에 대해서 한 번씩 호출된다.

에디터

Reset

오브젝트에 스크립트를 처음 연결하거나 에디터에서 Reset 명령을 사용할 때 호출된다. 보통 스크립트의 프로퍼티를 초기화하기 위해서 사용한다.

(인스펙터에서 본 Reset 명령의 모습)

OnValidate

위의 흐름도에는 존재하지 않지만, OnValidate 함수 또한 에디터 단계에서 호출되는 함수이다. 이는 스크립트의 프로퍼티가 설정될 때마다 호출된다. 예를 들어, 에디터에서 씬을 열 때, IDE에서 코드를 수정 후 유니티에서 다시 로드될 때, 스크립트 컴포넌트를 인스펙터에서 수정할 때 등 다양한 시기에 발동된다.

에디터 단계에 있는 콜백 함수들은 런타임 환경(플레이 모드)에서는 실행되지 않는다. 전체 생명주기에서 완전 동떨어진 단계라, 별도의 단계라고 생각하는 것이 편하다.

첫 번째 프레임 업데이트 전

Start

스크립트 컴포넌트가 활성화된 경우에만 첫 번째 프레임 업데이트 전에 호출된다.
씬 에셋의 일부인 오브젝트의 경우 모든 스크립트에 대해 Update가 호출되기 전에 Start 함수가 호출된다. 그러나 게임플레이 중에 오브젝트를 인스턴스화할 때는 다르다. 예를 들어 다른 오브젝트의 Update 함수에서 오브젝트를 인스턴스화하는 경우, 원래 오브젝트에서 Update가 처음 실행되기 직전이 될 때까지 Start를 호출할 수 없다.

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

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

    private void Update()
    {
        if(Input.GetMouseButtonDown(0))
        {
            Debug.Log("Instantiate!");
            Instantiate(this);
            Debug.Log("Instantiate End!");
        }
    }
}

다음과 같이 마우스 왼쪽 클릭을 하면 똑같은 오브젝트가 복제되는 스크립트를 써보자. 이 경우에 마우스 한번을 클릭했을 시,

다음과 같은 로그가 찍히게 된다. 먼저 Instantiate가 실행되면, 복제된 객체의 Awake 함수가 실행되고, 그 후 진행하던 Update가 끝나고 복제된 객체의 Update가 실행되기 직전에 Start 함수가 실행되는 것이다.
즉, Start 함수는 Awake 함수 다음이라고 생각하기 보다는, Update 함수 바로 전에 호출된다고 생각하는 것이 타당하다.

업데이트 순서

FixedUpdate

FixedUpdate는 정해진 시간마다 한번 호출이 된다. 이는 보장된 타이머로 똑같은 시간마다 호출되기 때문에, 때로는 Update보다 많이, 때로는 적게 호출될 수 있다. 이 시간은 Edit > Project Settings > Time > Fixed Timestep에서 조정할 수 있다.
이후에 물리적 처리가 진행이 되어, OnCollisionXXX, OnTriggerXXX 같은 콜백 함수들이 필요한 경우 호출된다.

Update

Update는 프레임당 한번 호출이 된다. 하지만 프레임이 업데이트되는 시간이 일정하지 않으므로, 그를 나타낸 값인 Time.deltaTime은 항상 달라진다.
Update 함수가 반환된 후에는 코루틴 업데이트가 실행된다. 코루틴은 주어진 YieldInstruction, 즉 yield 다음에 오는 여러 속성이 완료될 때까지 실행을 잠시 멈추는 함수이다. 예를 들어 yield WaitForSeconds는, 지정된 초 이후에 모든 Update가 끝난 이후, 그 다음 동작을 실행한다.

LateUpdate

LateUpdate는 Update가 실행된 다음 바로 호출된다. LateUpdate는 Update의 계산이 끝났다는 것을 보장하므로, Update의 계산이 끝난 후에 호출할 필요가 있는 행동들에 주로 사용된다.

이런 Update 함수들은 같은 MonoBehaviour 스크립트끼리는 순서를 정할 수 없으나, 서로 다른 스크립트끼리는 Edit > Project Settings > Script Execution Order로 Update 순서를 지정할 수 있다.

애니메이션 업데이트

애니메이션 업데이트는 그 애니메이터의 Update Mode 등 여러 조건에 의해 다른 주기로 나타날 수 있다.

  • Normal: Update 호출과 같이 싱크된다.
  • Animate Physcis: Fixed Update와 같이 싱크된다. RigidBody를 쓰는 오브젝트와 같이 물리 연산이 필요한 모션을 애니메이팅하는 경우에는 이 옵션을 사용해야 위화감 없이 작동한다.
  • Unscaled Time: Update 호출과 같이 싱크되지만, TimeScale에 영향을 받지 않는다.

MonoBehaviour 스크립트에서 호출되는 콜백 함수는 OnAnimatorMove, OnAnimatorIK가 있다. 추가 애니메이션 관련 콜백 함수는 StateMachineBehaviour 스크립트에서 호출된다. OnStateMachineEnter, OnStateMachineExit, OnStateEnter, OnStateUpdate, OnStateExit 등이 있다.

애니메이션 함수들은 프로파일러 마커가 연결되어 있다. 즉, 유니티 프로파일러를 사용해 언제 호출하는지 알아볼 수 있다.

렌더링

이 렌더링 관련 콜백 함수들은 사용자가 렌더링 관련 파이프라인을 직접 구성할 수 있는 SRP(Scriptable Rendering Pipeline)이 아닌, 빌트인 파이프라인에만 동작한다.

오브젝트 파괴/비활성화 시

OnDestroy

오브젝트가 존재하는 마지막 씬의 모든 업데이트 이후 호출된다. 씬 종료시에도 오브젝트가 파괴된다는 판정이기 때문에 호출된다.

OnDisable

오브젝트가 비활성 상태가 될 시 호출된다.

종료할 때

OnApplicationQuit

애플리케이션이 종료되기 전, 모든 게임 오브젝트에서 호출되는 함수이다. 에디터에서는 Play Mode가 종료될 때 호출된다.


레퍼런스

profile
마포고개발짱

0개의 댓글