Unity 25일차 - Unity 팀 프로젝트

한예준·2025년 5월 13일

오늘도 Unity 팀 프로젝트 작업을 진행했다. 커스터마이징, 도전과제 시스템을 어느정도 완성하였는데, 이 과정에서 몇 가지 문제가 발생했다.


트러블슈팅 (커스터마이징 시스템)

배경

  • 처음엔 플레이어 프리팹 자체를 변경시키는 방식으로 커스터마이징을 하려 했으나, 스프라이트와 애니메이션 정도만 변경하면 커스터마이징 시스템을 구현할 수 있을 거라 생각했다.
  • 하지만 스킨 변경 시 Animator가 갱신되지 않아 제대로 애니메이션이 작동하지 않는 모습을 보였다.

발단 및 전개

  • 기본 스킨(DefaultSkin)으로 게임을 시작하면 정상적으로 Animator가 동작하지만 캐릭터 선택 UI에서 스킨을 변경할 시, 기존 스킨과 변경 스킨이 동시에 보이는 현상이 발생하였다.
    • 이를 해결하기 위해 플레이어 프리팹에 빈 자식 오브젝트인 SkinHolder를 생성하고, 스프라이트를 여기에 넣어주었다.
    • 스프라이트에는 애니메이터와 파티클이펙트가 포함되어 있다.
  • SkinManager.ApplySkin을 통해 스킨을 교체할 시, SkinHolder 내에 있는 모든 오브젝트를 Destroy하고 새 스프라이트 프리팹을 넣어주도록 짰다.
  • 그러나 PlayerMovement.animator 필드는 이전 Animator 참조를 가리켰다.
  • 이후 점프, 피격 애니메이션 등의 animator.SetTrigger(...) 호출 시
    NullReferenceException: Object reference not set to an instance of an object
    • NRE오류가 발생하였다.

위기

  • 원인은 오브젝트를 파괴했을 때 붙어있던 Animator도 제거되면서 새로운 프리팹을 붙였을 때 그 프리팹의 Animator를 참조해야 하는데, 이를 놓쳤기 때문이다.
  • 즉, PlayerMovement.cs/PlayerHealth 스크립트가 animator필드에서 파괴된 애니메이터를 계속 가리키고 있기 때문에 NRE오류가 발생한 것이다.

해결

  • SkinManager.ApplySkin에서
        var newAnim = goSkin.GetComponent<Animator>();
        if (newAnim != null)
        {
            var movement = player.GetComponent<PlayerMovement>();
            movement.animator = newAnim;

            var health = player.GetComponent<PlayerHealth>();
            if (health != null)
                health.AssignAnimator(newAnim);


            if (skin.data.animatorOverride != null)
                newAnim.runtimeAnimatorController = skin.data.animatorOverride;
        }

를 통해 새로운 애니메이터를 곧바로 PlayerMovement.csPlayerHealth.cs에 할당해주었다.

0개의 댓글