Quick Comparison
UnityEvent, C# event, Action은 모두 callback을 여러 곳에 연결할 수 있지만 저장 위치와 발행 권한이 다릅니다. 반환값과 validation이 필요하면 callback broadcast가 아니라 direct method 또는 Func contract를 먼저 검토합니다.
| 요구 | 선택 | owner와 제한 |
|---|---|---|
| prefab·Inspector에서 designer가 연결 | UnityEvent persistent listener | scene/prefab reference와 refactor 확인 |
| code-only notification API | public C# event | publisher만 invoke, subscriber가 해제 |
| 짧은 내부 callback 전달 | Action parameter/field | 호출 기간과 null·dispose 처리 |
| result·승인·실패를 즉시 반환 | direct call / Func | caller가 result를 처리 |
| retry·ordering·durability가 필요 | queue/message system | delivery·duplicate·acknowledgement |
public sealed class Health : MonoBehaviour
{
public event Action<int, int> Changed;
public void ApplyDamage(int amount)
{
currentHp = Mathf.Max(0, currentHp - amount);
Changed?.Invoke(currentHp, maxHp);
}
}
void OnEnable() => health.Changed += UpdateBar;
void OnDisable() => health.Changed -= UpdateBar;UnityEvent listener의 두 종류
Inspector에 저장된 persistent listener는 prefab/scene serialized data의 일부입니다. runtime의 AddListener는 non-persistent listener를 추가하며, RemoveListener와 RemoveAllListeners도 runtime listener만 대상으로 합니다. 그러므로 RemoveAllListeners로 Inspector 연결까지 지워진다고 가정하지 않고, button prefab의 persistent target이 scene 전환 뒤에도 유효한지 확인합니다.
UnityEvent는 UI button, small prefab effect, designer가 조합하는 단순 signal에 유용합니다. 다만 gameplay core rule을 UnityEvent chain으로 연결하면 code search만으로 call graph·execution order·payload consumer를 찾기 어려워집니다. Inspector event도 contract name, payload 의미, enabled/disabled listener policy를 적어 둡니다.
event와 Action의 수명
C# event는 publisher type 외부에서 invoke하지 못하게 해 notification API의 발행 권한을 제한합니다. subscriber는 long-lived publisher를 구독한 뒤 해제하지 않으면 destroyed object가 참조되거나 memory가 오래 유지될 수 있으므로 OnEnable/OnDisable, Dispose, scene scope 중 한 해제 경계를 갖습니다.
Action은 method argument·private field처럼 짧은 callback을 전달할 때 간단합니다. 외부 consumer가 add/remove하고 publisher가 반복 발행하는 public API라면 Action field를 public으로 노출하는 것보다 event Action이 의도를 더 잘 드러냅니다. handler는 기본적으로 synchronous하게 호출되므로 listener 순서, exception, re-entrant mutation에 core rule을 의존시키지 않습니다.
확인할 실패
동일 listener를 여러 번 등록했는지, object disable 후 해제됐는지, persistent target이 missing인지, event handler가 publisher state를 다시 바꾸는지 test합니다. notification은 과거형(HealthChanged)으로, 명령은 동사형(RequestDamage)으로 이름을 나누면 caller가 결과를 기다려야 하는 흐름과 broadcast를 구분하기 쉽습니다.
UnityEvent를 선택했다고 listener lifecycle이 자동으로 해결되지는 않습니다. persistent와 runtime listener를 구분하고, 누가 연결·해제·실행 순서를 소유하는지 설명할 수 있어야 합니다.
참고 링크
3 sources