유니티 라이프사이클

2024. 5. 27. 21:15·유니티

1. MonoBehaviour 생명주기(Lifecycle)란?

씬(Scene)에 배치된 활성화된 게임 오브젝트에 부착된 모든 MonoBehaviour 스크립트 인스턴스는 Unity 엔진에 의해 관리되는 일련의 단계를 거칩니다. 이를 '생명주기'라고 할 수 있으며, 크게 다음과 같은 단계들로 구성됩니다.

  • 초기화(Initialization): 스크립트 인스턴스가 로드되고 처음 활성화될 때 필요한 설정을 수행하는 단계.
  • 물리 업데이트(Physics Update): 물리 엔진 계산 및 관련 로직이 실행되는 단계.
  • 게임 로닉 업데이트(Game Logic Update): 프레임 기반의 주요 게임 로직, 입력 처리 등이 실행되는 단계.
  • 렌더링(Rendering): 씬을 화면에 그리는 단계 (스크립트에서 직접 제어하기보다는 결과에 영향을 주는 단계).
  • 해체(Decommissioning): 스크립트 인스턴스나 게임 오브젝트가 비활성화되거나 파괴될 때 정리 작업을 수행하는 단계.

Unity는 이러한 각 단계와 관련된 특정 시점에 호출될 수 있는 '매직 메서드(Magic Methods)'들을 제공합니다. 개발자는 MonoBehaviour를 상속받는 클래스 내에 이 메서드들을 선언하고 코드를 작성함으로써, 원하는 시점에 원하는 로직이 실행되도록 할 수 있습니다.


2. 주요 생명주기 메서드 실행 순서 및 역할

가장 중요하고 자주 사용되는 MonoBehaviour 생명주기 메서드들의 일반적인 실행 순서는 다음과 같습니다. (주의: 이는 단일 스크립트 인스턴스 내에서의 순서이며, 서로 다른 스크립트 간의 실행 순서는 'Script Execution Order' 설정을 통해 제어할 수 있습니다.)

  • 초기화 단계 (Initialization Phase)

    1. Awake(): 스크립트 인스턴스가 로드될 때 단 한 번 호출됩니다. (게임 오브젝트나 스크립트가 비활성화 상태여도 호출됨). 다른 모든 게임 오브젝트의 초기화나 Start() 메서드 호출 전에 실행되는 것이 보장됩니다. 주로 자기 자신의 컴포넌트 참조 설정이나 내부 상태 초기화에 사용됩니다.
    2. OnEnable(): 게임 오브젝트와 스크립트가 활성화될 때마다 호출됩니다. Awake() 다음에 호출되며, 게임 도중 비활성화되었다가 다시 활성화될 때도 호출됩니다. 이벤트 리스너 등록이나 활성화 상태에 따른 초기 설정에 적합합니다.
    3. Start(): 스크립트 인스턴스가 활성화된 상태에서 첫 번째 프레임 업데이트 직전에 단 한 번 호출됩니다. 모든 Awake() 호출이 완료된 후에 호출되는 것이 보장됩니다. 다른 스크립트와의 상호작용이 필요한 초기화나, 활성화된 상태에서 시작할 때 필요한 로직에 사용됩니다.
  • 물리 업데이트 단계 (Physics Phase)

    • FixedUpdate(): 고정된 시간 간격(Time.fixedDeltaTime, 기본값 0.02초)으로 호출됩니다. 프레임 속도와는 독립적으로 실행됩니다. 모든 물리(Physics) 관련 계산(Rigidbody에 힘 가하기, 충돌 처리 기반 로직 등)은 이 메서드 내에서 수행해야 일관된 결과를 얻을 수 있습니다. 한 프레임 동안 여러 번 호출되거나 한 번도 호출되지 않을 수 있습니다.
  • 게임 로직 업데이트 단계 (Game Logic Phase)

    1. Update(): 매 프레임마다 한 번 호출됩니다. 호출 간격은 프레임 속도에 따라 달라집니다 (가변적). 대부분의 게임 로직(비-물리 이동, 입력 처리, 타이머, AI 로직 등)을 처리하는 데 사용됩니다. Time.deltaTime을 사용하여 프레임 속도 변화에 따른 영향을 보정해야 합니다.
    2. LateUpdate(): 모든 Update() 함수가 호출된 후, 매 프레임마다 한 번 호출됩니다. 주로 카메라 이동 로직(캐릭터가 Update에서 이동한 후 따라가도록), 캐릭터의 최종 위치/상태에 기반한 IK(Inverse Kinematics) 조정 등 모든 업데이트가 완료된 후에 실행되어야 하는 로직에 사용됩니다.
  • 렌더링 단계 (Rendering Phase)

    • (이 단계의 메서드는 게임 로직보다는 렌더링 제어에 관련됩니다)
    • OnGUI(): 레거시 GUI(IMGUI) 시스템을 사용하여 UI를 그릴 때 호출됩니다 (현재는 UGUI나 UI Toolkit 사용이 권장됨). 매 프레임 여러 번 호출될 수 있습니다.
    • 기타 렌더링 콜백 (OnRenderObject, OnWillRenderObject 등): 고급 렌더링 제어를 위해 사용됩니다.
  • 비활성화 및 파괴 단계 (Deactivation and Destruction Phase)

    1. OnDisable(): 게임 오브젝트나 스크립트가 비활성화될 때마다 호출됩니다. OnDestroy() 전에 호출되며, 게임 도중 비활성화될 때도 호출됩니다. OnEnable에서 등록했던 이벤트 리스너 해제 등 활성화 상태와 관련된 정리 작업에 사용됩니다. OnEnable()의 반대 역할을 합니다.
    2. OnDestroy(): 게임 오브젝트나 컴포넌트가 파괴되기 직전에 단 한 번 호출됩니다. 애플리케이션 종료 시에도 호출될 수 있습니다. 모든 최종적인 정리 작업(외부 리소스 해제, 구독 완전 해지, 다른 시스템에 파괴 알림 등)을 수행하는 곳입니다.

3. 각 메서드의 상세 설명 및 활용

  • Awake():
    • 언제? 스크립트 인스턴스 로드 시 1회. Start() 보다 먼저, 활성화 여부 상관없이.
    • 무엇을? 자기 자신의 상태 초기화, 같은 게임 오브젝트 내 다른 컴포넌트 참조 설정 (GetComponent 등). 다른 스크립트와의 상호작용은 피하는 것이 좋음 (아직 Awake가 실행되지 않았을 수 있음).
  • OnEnable():
    • 언제? 객체/스크립트 활성화 시마다. Awake() 다음, Start() 이전 (첫 활성화 시).
    • 무엇을? 이벤트 구독(+=), 필요한 리소스 할당, 활성화 시 필요한 초기 상태 설정.
  • Start():
    • 언제? 활성화된 상태에서 첫 프레임 업데이트 직전 1회. 모든 Awake() 완료 후.
    • 무엇을? 다른 스크립트의 초기화가 완료된 후 수행해야 하는 초기화 로직, 다른 객체 참조 설정, 초기 게임 로직 시작.
  • FixedUpdate():
    • 언제? 고정된 시간 간격 (물리 업데이트 주기). 프레임당 0회 또는 여러 번.
    • 무엇을? Rigidbody를 사용한 물리 기반 이동, 힘/토크 적용, 물리 관련 계산. 반드시 Time.fixedDeltaTime 사용.
  • Update():
    • 언제? 매 프레임 1회. 프레임 속도에 따라 간격 변동.
    • 무엇을? 비-물리 기반 로직 (대부분의 게임 로직), 사용자 입력 감지, 타이머 업데이트, 애니메이션 제어(상태 전환 등), 비-물리 이동. 반드시 Time.deltaTime 사용.
  • LateUpdate():
    • 언제? 매 프레임 1회. 모든 Update() 완료 후.
    • 무엇을? 카메라 추적 로직, 절차적 애니메이션(IK 등) 조정, 모든 상태 업데이트가 끝난 후 필요한 최종 정리/계산.
  • OnDisable():
    • 언제? 객체/스크립트 비활성화 시마다. OnDestroy() 이전.
    • 무엇을? 이벤트 구독 취소(-=), 리소스 임시 해제, 비활성화 시 필요한 상태 정리. OnEnable에서 한 작업의 반대 작업 수행.
  • OnDestroy():
    • 언제? 객체/컴포넌트 파괴 직전 1회.
    • 무엇을? 모든 리소스 최종 해제, 영구적인 구독 해지, 외부 시스템에 파괴 알림.

4. 생명주기 메서드 사용 시 주의사항

  • 성능: Update, FixedUpdate, LateUpdate는 매우 자주 호출되므로, 이 메서드들 안에서는 무거운 계산, 불필요한 메모리 할당(가비지 생성), 비효율적인 API 호출(특히 Find 계열)을 피해야 합니다. 성능 문제가 발생하면 프로파일러를 통해 이 메서드들을 먼저 확인해야 합니다.
  • 스크립트 간 실행 순서: 기본적으로 서로 다른 스크립트의 동일한 생명주기 메서드(예: 여러 개의 Update 메서드) 호출 순서는 보장되지 않습니다. 특정 스크립트가 다른 스크립트보다 먼저 실행되어야 하는 의존성이 있다면, Edit > Project Settings > Script Execution Order 메뉴에서 실행 순서를 명시적으로 지정해야 합니다.
  • Awake vs. Start: 두 메서드 모두 초기화에 사용되지만 호출 시점과 보장되는 조건이 다릅니다. 일반적으로 자신의 초기화는 Awake에서, 다른 객체와의 상호작용이 필요한 초기화는 Start에서 수행하는 것이 안전합니다.
  • Update vs. FixedUpdate: 물리 관련 로직은 반드시 FixedUpdate에서, 그 외 대부분의 로직은 Update에서 처리해야 합니다. 혼용 시 예측 불가능한 동작(예: 떨림 현상, 물리 계산 오류)이 발생할 수 있습니다.
  • 구독 해지: OnEnable에서 이벤트를 구독했다면, 반드시 OnDisable에서 해당 이벤트를 구독 취소해야 메모리 누수와 오류를 방지할 수 있습니다. 이는 매우 중요하고 자주 실수하는 부분입니다.
  • 코루틴: StartCoroutine은 Awake, Start, Update 등 대부분의 생명주기 메서드 내에서 호출될 수 있습니다. 코루틴은 자체적인 실행 흐름을 가지지만, 시작점은 생명주기와 연관됩니다.

5. 실행 순서 요약

주요 생명주기 메서드의 기본적인 실행 흐름은 다음과 같습니다.

  1. (최초 로드 시) Awake()
  2. (최초 활성화 시) OnEnable()
  3. (활성화 상태에서 첫 프레임 전) Start()
  4. --- 게임 루프 시작 ---
    • (물리 스텝) FixedUpdate() (0회 이상 호출될 수 있음)
    • (게임 로직) Update() (1회 호출)
    • (후처리 로직) LateUpdate() (1회 호출)
    • (렌더링)
  5. --- 게임 루프 반복 ---
  6. (비활성화 시) OnDisable()
  7. (활성화 시) OnEnable() (다시 활성화될 경우)
  8. (파괴 시) OnDestroy()

(이 외에도 많은 이벤트 함수들이 존재하며, 자세한 순서는 Unity 공식 문서를 참고하는 것이 가장 정확합니다.)


결론

Unity의 MonoBehaviour 생명주기 메서드들은 개발자가 Unity 엔진의 실행 흐름에 개입하여 커스텀 로직을 삽입할 수 있도록 설계된 강력하고 필수적인 기능입니다. Awake, Start를 통한 체계적인 초기화, FixedUpdate를 이용한 안정적인 물리 처리, Update와 LateUpdate를 통한 유연한 게임 로직 및 카메라 제어, 그리고 OnDisable, OnDestroy를 통한 깔끔한 정리 작업은 잘 구조화되고 성능 좋은 게임을 만드는 데 핵심적인 역할을 합니다. 각 메서드의 정확한 호출 시점과 목적을 이해하고, 성능 및 스크립트 간 실행 순서와 같은 주의사항을 인지하며 상황에 맞게 올바르게 활용하는 것이 Unity C# 스크립팅의 기본이자 가장 중요한 부분 중 하나입니다. 이 생명주기에 대한 깊이 있는 이해는 Unity 개발의 효율성과 코드 품질을 크게 향상시킬 것입니다.


참고 자료

  • Unity 매뉴얼 - 이벤트 함수의 실행 순서 (Order of execution for event functions) (가장 중요하고 상세한 자료)
  • Unity 스크립팅 레퍼런스 - MonoBehaviour (각 생명주기 메서드 설명 링크 포함)
'유니티' 카테고리의 다른 글
  • FixedUpdate와 물리 로직
  • 초기화 이벤트 함수 비교
  • UnityEngine 클래스 상속 계층
  • UI 배경 Dim 처리
뇌장하드 주인장
뇌장하드 주인장
  • 뇌장하드 주인장
    뇌장하드
    뇌장하드 주인장
    • 분류 전체보기 (86)
      • C++ (9)
      • C# (15)
      • CS (9)
      • 유니티 (38)
      • 유니팁 (7)
      • 유니티 패턴 (8)
      • - (0)
  • 블로그 메뉴

    • 홈
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
뇌장하드 주인장
유니티 라이프사이클
상단으로

티스토리툴바