유니티 함수 실행 순서

Unity의 생명주기 함수 실행 순서를 학습합니다. Awake, Start, Update 등의 함수가 언제 실행되는지 이해합니다.

Unity는 스크립트의 생명주기에 따라 특정 순서로 함수(function)를 실행합니다. 이 순서를 이해하는 것은 Unity 개발에서 매우 중요합니다.

주요 함수(function) 실행 순서

1. Awake()          - 객체가 생성될 때 (한 번만)
2. OnEnable()       - 객체가 활성화될 때
3. Start()          - 첫 프레임 전에 (한 번만)
4. FixedUpdate()    - 물리 업데이트 (고정 주기)
5. Update()         - 매 프레임마다
6. LateUpdate()     - 모든 Update() 후
7. OnGUI()          - GUI 렌더링
8. OnDisable()      - 객체가 비활성화될 때
9. OnDestroy()      - 객체가 파괴될 때

상세 설명

Awake()

void Awake()
{
    // 객체가 생성될 때 가장 먼저 실행
    // 다른 객체의 참조를 초기화할 때 사용
    // Scene이 로드될 때 모든 Awake()가 실행된 후 Start() 실행
    Debug.Log("Awake 실행");
}

특징:

  • Scene이 로드될 때 모든 객체(object)Awake()가 먼저 실행됨
  • 다른 객체(object)의 참조를 초기화할 때 사용
  • Start()보다 먼저 실행됨

OnEnable()

void OnEnable()
{
    // 객체가 활성화될 때마다 실행
    // GameObject가 활성화되거나 스크립트가 활성화될 때
    Debug.Log("OnEnable 실행");
}

특징:

  • GameObject나 스크립트가 활성화될 때마다 실행
  • Awake() 이후, Start() 이전에 실행
  • 여러 번 실행될 수 있음

Start()

void Start()
{
    // Awake() 이후, 첫 Update() 전에 실행
    // 다른 객체가 모두 준비된 후 초기화할 때 사용
    // 한 번만 실행됨
    Debug.Log("Start 실행");
}

특징:

  • 모든 Awake()가 실행된 후 실행
  • 첫 번째 프레임 전에 실행
  • 한 번만 실행됨
  • 다른 객체(object)의 초기화가 완료된 후 사용

FixedUpdate()

void FixedUpdate()
{
    // 고정된 시간 간격으로 실행 (기본 0.02초)
    // 물리 계산에 사용 (Rigidbody 등)
    // Time.fixedDeltaTime 사용
}

특징:

  • 고정된 시간 간격으로 실행 (기본 0.02초 = 50Hz)
  • Time.fixedDeltaTime으로 시간 간격 조정 가능
  • 물리 계산에 사용 (Rigidbody, Collider 등)
  • 프레임레이트와 무관하게 일정한 간격으로 실행

Update()

void Update()
{
    // 매 프레임마다 실행 (프레임레이트에 따라 다름)
    // 입력 처리, 게임 로직 등에 사용
    // Time.deltaTime 사용
}

특징:

  • 매 프레임마다 실행
  • 프레임레이트에 따라 실행 횟수가 달라짐
  • 입력 처리, 게임 로직 등에 사용
  • Time.deltaTime으로 프레임 독립적인 계산 가능

LateUpdate()

void LateUpdate()
{
    // 모든 Update()가 끝난 후 실행
    // 카메라 추적 등에 사용
}

특징:

  • 모든 Update()가 실행된 후 실행
  • 카메라 추적, UI 업데이트 등에 사용
  • 다른 객체(object)의 위치가 확정된 후 작업할 때 유용

OnGUI()

void OnGUI()
{
    // GUI 렌더링을 위한 함수
    // 매 프레임 여러 번 호출될 수 있음
    // 레거시 GUI 시스템 사용 시에만 필요
}

특징:

  • GUI 렌더링을 위한 함수(function)
  • 매 프레임 여러 번 호출될 수 있음
  • 레거시 GUI 시스템 (IMGUI) 사용 시에만 필요
  • 최신 UI 시스템 (uGUI) 사용 시 불필요

OnDisable()

void OnDisable()
{
    // 객체가 비활성화될 때 실행
    // GameObject나 스크립트가 비활성화될 때
    Debug.Log("OnDisable 실행");
}

특징:

  • GameObject나 스크립트가 비활성화될 때 실행
  • 여러 번 실행될 수 있음
  • 이벤트(event) 구독 해제 등에 사용

OnDestroy()

void OnDestroy()
{
    // 객체가 파괴될 때 실행
    // Scene이 종료되거나 GameObject가 Destroy될 때
    Debug.Log("OnDestroy 실행");
}

특징:

  • GameObject가 파괴될 때 실행
  • Scene이 종료될 때도 실행
  • 리소스 정리, 이벤트(event) 구독 해제 등에 사용

실행 순서 예시

public class ExecutionOrderExample : MonoBehaviour
{
    void Awake()
    {
        Debug.Log("1. Awake");
    }
    
    void OnEnable()
    {
        Debug.Log("2. OnEnable");
    }
    
    void Start()
    {
        Debug.Log("3. Start");
    }
    
    void FixedUpdate()
    {
        Debug.Log("4. FixedUpdate");
    }
    
    void Update()
    {
        Debug.Log("5. Update");
    }
    
    void LateUpdate()
    {
        Debug.Log("6. LateUpdate");
    }
    
    void OnDisable()
    {
        Debug.Log("7. OnDisable");
    }
    
    void OnDestroy()
    {
        Debug.Log("8. OnDestroy");
    }
}

실행 순서 다이어그램

Scene 로드
    ↓
[Awake] 모든 객체의 Awake() 실행
    ↓
[OnEnable] 활성화된 객체의 OnEnable() 실행
    ↓
[Start] 모든 객체의 Start() 실행
    ↓
┌─────────────────────────┐
│   매 프레임 반복         │
│                         │
│  [FixedUpdate]          │
│  [Update]               │
│  [LateUpdate]           │
│  [OnGUI]                │
└─────────────────────────┘
    ↓
[OnDisable] 비활성화 시
    ↓
[OnDestroy] 파괴 시

실전 활용 예시

예시 1: 초기화 순서 보장

public class Manager : MonoBehaviour
{
    public static Manager Instance;
    
    void Awake()
    {
        // 싱글톤 초기화 (가장 먼저)
        if (Instance == null)
        {
            Instance = this;
            DontDestroyOnLoad(gameObject);
        }
        else
        {
            Destroy(gameObject);
        }
    }
    
    void Start()
    {
        // 다른 객체들이 모두 준비된 후 초기화
        InitializeGame();
    }
    
    void InitializeGame()
    {
        // 게임 초기화 로직
    }
}

예시 2: 물리와 일반 업데이트 분리

public class PlayerController : MonoBehaviour
{
    private Rigidbody rb;
    private Vector3 input;
    
    void Start()
    {
        rb = GetComponent<Rigidbody>();
    }
    
    void Update()
    {
        // 입력 처리 (프레임레이트에 따라 다름)
        input = new Vector3(
            Input.GetAxis("Horizontal"),
            0,
            Input.GetAxis("Vertical")
        );
    }
    
    void FixedUpdate()
    {
        // 물리 이동 (고정된 시간 간격)
        rb.AddForce(input * 10f);
    }
}

예시 3: 카메라 추적

public class CameraFollow : MonoBehaviour
{
    public Transform target;
    private Vector3 offset;
    
    void Start()
    {
        offset = transform.position - target.position;
    }
    
    void LateUpdate()
    {
        // 모든 Update()가 끝난 후 카메라 위치 업데이트
        transform.position = target.position + offset;
    }
}

주의사항

  1. Awake vs Start: Awake()는 다른 객체(object) 초기화 전, Start()는 모든 객체(object) 초기화 후
  2. Update vs FixedUpdate: 일반 로직은 Update(), 물리 계산은 FixedUpdate()
  3. OnEnable/OnDisable: 여러 번 실행될 수 있으므로 주의
  4. OnDestroy: 리소스 정리와 이벤트(event) 구독 해제 필수

참고 자료

Unity 공식 문서: Execution Order


← 목차로 돌아가기