빠른 흐름
private void OnEnable()
{
GameEvents.OnEnemyDied += HandleEnemyDied;
GameEvents.OnLevelUp += HandleLevelUp;
}
private void OnDisable()
{
GameEvents.OnEnemyDied -= HandleEnemyDied;
GameEvents.OnLevelUp -= HandleLevelUp;
}기본 흐름
호출 시점과 반복성
OnEnable은 GameObject가 활성화(active = true)될 때마다 호출됩니다. 처음 활성화될 때도, 비활성화 후 다시 활성화할 때도 매번 호출됩니다. OnDisable은 비활성화될 때 호출되고, 오브젝트 파괴나 스크립트 리로드 직전에도 함께 호출될 수 있습니다.
이 반복성이 Awake/Start와의 핵심 차이입니다. "한 번만 실행할 초기화"는 Awake/Start에, "활성 상태에 묶인 구독·등록"은 OnEnable/OnDisable에 두는 이유입니다.
Awake → OnEnable → Start → (프레임 루프) → OnDisable
↑ ↓
└──────── 껐다 켤 때마다 ──────┘이벤트 구독·해제 패턴
OnEnable에서 구독하고 OnDisable에서 해제하는 패턴이 기본입니다. 해제를 빠뜨리면 비활성화된 오브젝트가 이벤트를 계속 받아 NullReferenceException이나 예기치 않은 동작이 생길 수 있습니다. 오브젝트 풀에서 재사용하는 오브젝트라면 이 문제가 더 자주 터집니다.
// C# 이벤트
private void OnEnable() { PlayerHealth.OnDamaged += UpdateHealthBar; }
private void OnDisable() { PlayerHealth.OnDamaged -= UpdateHealthBar; }
// UnityEvent (버튼 등)
private void OnEnable() { submitButton.onClick.AddListener(OnSubmit); }
private void OnDisable() { submitButton.onClick.RemoveListener(OnSubmit); }코루틴 관리
코루틴을 오브젝트 활성화 수명과 함께 관리하려면 OnEnable에서 시작하고 OnDisable에서 중단합니다.
private Coroutine _blinkHandle;
private void OnEnable()
{
_blinkHandle = StartCoroutine(BlinkRoutine());
}
private void OnDisable()
{
if (_blinkHandle != null)
{
StopCoroutine(_blinkHandle);
_blinkHandle = null;
}
}오브젝트가 SetActive(false)되면 코루틴이 자동 중단되기는 하지만, OnDisable에서 핸들을 명시적으로 null로 초기화해두면 재활성화 시 _blinkHandle != null 검사에서 꼬이는 것을 방지할 수 있습니다.
Input System Action Map 연동
Input System을 쓸 때 OnEnable/OnDisable에 Action Map 활성화를 연결하면 UI와 게임플레이 입력 컨텍스트를 자동으로 전환할 수 있습니다.
[SerializeField] private InputActionAsset actions;
private InputActionMap _gameplayMap;
private void Awake()
{
_gameplayMap = actions.FindActionMap("Gameplay");
}
private void OnEnable() { _gameplayMap.Enable(); }
private void OnDisable() { _gameplayMap.Disable(); }체크포인트
| 메서드 | 호출 시점 | 추천 용도 |
|---|---|---|
OnEnable | 활성화될 때마다 | 이벤트 구독, 코루틴 시작, Action Map 활성화 |
OnDisable | 비활성화될 때마다 | 이벤트 해제, 코루틴 중단, Action Map 비활성화 |
| 작업 | Awake/Start | OnEnable/OnDisable |
|---|---|---|
| 컴포넌트 캐싱 | ✅ (1회) | — |
| 외부 참조 연결 | ✅ (Start) | — |
| 이벤트 구독/해제 | ❌ (반복 위험) | ✅ |
| 코루틴 시작/중단 | 상황에 따라 | ✅ (활성 수명 연동) |
| Input Action 활성화 | — | ✅ |
주의할 점
OnEnable에서 구독한 이벤트는 보통 OnDisable에서 함께 해제하는 편이 가장 안전합니다. OnDestroy에서만 해제하면 비활성화 중에도 이벤트를 받을 수 있고, 오브젝트 풀링처럼 재사용하는 구조에서는 구독이 중복으로 쌓입니다. 다만 오브젝트가 비활성화돼도 계속 들어야 하는 전역 구독이라면 다른 수명주기 지점을 의도적으로 선택해야 합니다.
참고 링크
2 sources