Unity6에서 AnimationClip.events 🔥 clip != null인데도 clip.events = null에서 예외가 나는 이유:
🔥 clip != null인데도 clip.events = null에서 예외가 나는 이유:
Unity 6부터는 AnimationClip.events 프로퍼티의 setter가 더 엄격해졌습니다.
- 읽기 전용 (ReadOnly) 상태의 AnimationClip에는 events를 설정할 수 없습니다.
- 이는 다음과 같은 경우에 해당됩니다:
| 🔒 AnimatorController에 바인딩된 AnimationClip | Read-only 이기 때문에 .events 수정 불가 |
| 🔒 Resources 또는 Project에서 직접 참조한 Clip | 런타임 수정 불가 |
| ✅ Instantiate()로 복사된 Clip | 수정 가능 |
✅ 해결 방법 1: clip.events = null 코드 제거 또는 예외 방지 처리
🔸 방법 A: try-catch 방어
if (clip != null)
{
try
{
clip.events = null;
}
catch (Exception e)
{
Debug.LogWarning($"clip.events = null failed on {clip.name} : {e.Message}");
}
}
🔸 방법 B: 애초에 clip이 수정 가능한지 확인
✅ 해결 방법 2: 수정 가능한 AnimationClip을 사용하는 구조로 리팩토링
AnimatorController에서 가져온 clip은 수정할 수 없기 때문에, 실행 시점에 복사본을 생성해서 사용하는 방식을 써야 안전합니다.
그 후에 이 clip에만 .events 설정을 수행하세요.
🧠 보너스: Unity 공식 문서에도 명시되어 있음
Unity 2023 이후 버전부터 일부 API는 런타임에서 리소스를 변경하려고 하면
NullReferenceException 또는 InvalidOperationException이 발생할 수 있습니다.
특히 AnimationClip.events는 내부적으로 C++ side가 null 상태일 경우 crash or exception 유발.
✅ 결론 정리
| 🔧 빠른 패치 | clip.events = null; 코드를 try-catch로 감싸거나, 해당 줄 제거 |
| 🔒 Unity 6 대응 | AnimationController에 종속된 clip은 수정 불가하므로, 복사본을 만들어서 .events 설정 필요 |
| 🧪 디버깅 확인 | clip.name 출력해보고, anim.clip == clip 확인해보면 원본인지 판단 가능 |
AnimationClip을 복사해서 .events를 수정하면,
실제 AnimatorController에서 실행 중인 애니메이션이 아닌 복사본이 실행되는 것 아닌가?
→ 그럼 이벤트도 안 호출될 수 있는 것 아닌가?
👉 맞습니다. 그냥 복사해서 수정만 해서는 작동하지 않습니다.
복사한 Clip을 Animator 또는 Animation에 적용하지 않으면 실행되지 않습니다.
🔍 Unity 애니메이션 시스템 별 차이
| Animator (AnimatorController) | 불가능 – 런타임 클립 교체 매우 복잡 | ❌ .events 수정 불가 | Unity의 메인 애니메이션 시스템 |
| Animation (Legacy Animation) | ✅ AddClip()으로 런타임 클립 교체 가능 | ✅ 이벤트 설정 가능 | Animation 컴포넌트 사용 시 가능 |
✅ Animation 컴포넌트일 경우 (지금 사용 중인 구조)
AnimationEndListener에서는 Animation 컴포넌트를 사용하고 있죠:
즉, Legacy Animation 시스템을 쓰고 있으므로, 복사한 AnimationClip을 anim에 등록해 사용하면 전혀 문제 없습니다.
🔸 안전하게 작동하는 코드 예시
✅ 이렇게 하면 복사본에 이벤트 등록 가능,
✅ Animation에서 해당 복사본이 실제로 실행되므로 OnEnd 이벤트 호출됨
✅ 기존 구조 그대로 유지 가능
❗ 단, Animator (Mecanim) 시스템이라면?
AnimatorController에서 사용하는 Animator는:
- 클립을 runtime에 교체하거나 이벤트를 추가하는 건 거의 불가능에 가까움
- AnimatorOverrideController로 대체하거나
- 타임라인/애니메이션 상태 종료 체크 등 다른 방식으로 이벤트 처리 필요
✅ 결론
| 복사한 Clip에 이벤트를 추가하면? | 그 복사본이 실행되지 않으면 아무 효과 없음 |
| Animation 컴포넌트 사용 중이라면? | 복사 후 AddClip() 및 Play()로 실행하면 문제 없음 |
| Animator 사용 중이라면? | 런타임 클립 교체는 어렵고 다른 방식 추천됨 |
🎁 참고로: AnimatorController 쓰는 경우 대안
- AnimatorStateBehaviour.OnStateExit 사용해서 애니메이션 종료 감지
- AnimationClip.length + Invoke() 로 타이머 기반 처리
- AnimatorOverrideController 사용해 런타임에 클립 교체
- Playable API로 완전 커스텀 애니메이션 제어 (복잡함)
혹시 Animator와 Animation이 혼용되었거나 향후 Animator로 전환 계획이 있으시다면,
같은 이벤트 처리를 Animator 스타일로 바꾸는 방법도 함께 제안드릴 수 있어요!