Unity Term Book
스크립팅 & 라이프사이클

Awake & Start

Awake는 객체가 생성될 때(비활성이어도) 한 번 호출되고 Start는 활성화된 첫 프레임에 실행됩니다. 모든 Awake가 끝난 뒤 안전히 연결하며 Singleton·Script Execution Order·교차 참조를 다룹니다. 실무에서 바로 쓰는 패턴을 익힙니다.

상상해 보세요...

Awake는 출근 전 개인 준비——옷 입고 열쇠 챙기기, 다른 사람 불필요. Start아침 킥오프 미팅——모두가 이미 자리에 있으니(모든 Awake 완료) 팀 간 업무(GameManager.Instance, 다른 객체 찾기…)를 배정할 수 있습니다.

개념 자세히

Awake()는 인스턴스가 생성될 때 정확히 한 번 호출됩니다——컴포넌트가 enabled = false여도. 내부 참조에 이상적: _rb = GetComponent<Rigidbody>().

Start()는 컴포넌트가 활성화된 뒤 첫 프레임에 실행됩니다. 씬의 모든 Awake()가 이미 끝난 뒤이므로 Start는 Singleton, 다른 객체 찾기, 이벤트 등록에 안전합니다. 비활성화 후 다시 켜도 Start는 다시 실행되지 않습니다.

실행 순서: Unity는 먼저 모든 스크립트의 Awake, 그다음 모든 스크립트의 Start를 돌립니다. 스크립트 간 순서는 Project Settings의 Script Execution Order를 정하지 않으면 미정의입니다.

런타임 Instantiate: 스폰된 객체도 Awake + Start를 받습니다. Awake는 Instantiate()가 반환되기 전에, Start는 다음 프레임 시작에 실행됩니다.

스크립트 간 실행 순서

⚡ AWAKE 단계 (첫 프레임 전)

GameManager.Awake()

_instance = this

PlayerCtrl.Awake()

_rb = GetComponent()

EnemyAI.Awake()

_nav = GetComponent()

🚀 START 단계 (첫 프레임)

GameManager.Start()

LoadLevel(1)

PlayerCtrl.Start()

GameManager.Instance ✅

EnemyAI.Start()

FindPlayer() ✅

🔄 Update 루프 (매 프레임)

실습 단계

1

Awake: 자기 초기화

GetComponent<T>() 캐시, 프라이빗 필드 초기화, Singleton 설정. 다른 객체를 호출하지 마세요.

2

Start: 바깥 세계와 연결

GameManager.Instance, FindObjectOfType<T>(), 이벤트 등록.

3

필요 시 Script Execution Order

Edit → Project Settings → Script Execution Order → 스크립트를 위로 드래그해 더 일찍 실행.

4

교차 스크립트 null 피하기

ScriptA.Awake가 아직 Awake 전인 ScriptB를 건드리면 null. 교차 접근은 Start에서.

인터랙티브 시뮬레이터

씬에 스크립트를 추가하고 Load Scene을 눌러 각 스크립트의 Awake 다음 Start를 확인하세요.

Scripts in Scene

Execution Log

스크립트를 추가한 뒤 Load Scene...

Phase: Idle|스크립트를 최소 2개 추가하고 Load Scene

코드 예제

기본

Awake에서 Singleton 패턴; 다른 컴포넌트는 Start에서 연결.

public class GameManager : MonoBehaviour
{
  public static GameManager Instance { get; private set; }

  void Awake()
  {
      // Singleton setup — runs before every Start()
      if (Instance != null) { Destroy(gameObject); return; }
      Instance = this;
      DontDestroyOnLoad(gameObject);
  }
}

public class PlayerController : MonoBehaviour
{
  private Rigidbody _rb;

  void Awake() => _rb = GetComponent<Rigidbody>();

  void Start()
  {
      // Safe: GameManager.Awake() already finished
      GameManager.Instance.RegisterPlayer(this);
  }
}

코드 예제

고급

[DefaultExecutionOrder] 특성으로 Awake 순서를 제어합니다.

using UnityEngine;

// Runs before other scripts (more negative = higher priority)
[DefaultExecutionOrder(-100)]
public class ServiceLocator : MonoBehaviour
{
  public static ServiceLocator Instance { get; private set; }
  private Dictionary<System.Type, MonoBehaviour> _services = new();

  void Awake()
  {
      Instance = this;
      // Auto-register every IService in the scene
      foreach (var svc in FindObjectsOfType<MonoBehaviour>())
          if (svc is IService)
              _services[svc.GetType()] = svc;
  }

  public T Get<T>() where T : MonoBehaviour =>
      _services.TryGetValue(typeof(T), out var s) ? s as T : null;
}

// Any script can fetch a service in Start:
// var gm = ServiceLocator.Instance.Get<GameManager>();

📌 빠른 정리

  • Awake: 자기 준비——다른 사람 불필요
  • Start: 씬과 연결——모든 Awake 이후
  • enable/disable로 Start가 다시 돌지 않음
  • 순서 고정에는 [DefaultExecutionOrder]

⚠️ 흔한 실수

  • ❌ Awake() 안에서 Singleton 접근

    Singleton이 아직 Awake 전일 수 있음 → NullReferenceException

    ✅ Singleton은 Start()에서 접근

  • ❌ Start()에서 Singleton 생성

    다른 스크립트 Awake가 끝날 때 Singleton이 아직 없음 → null

    ✅ Singleton은 항상 Awake()에서 생성