public class PlayerState
{
protected PlayerController _playerController;
protected Animator _animator;
public PlayerState(PlayerController playerController, Animator animator)
{
_playerController = playerController;
_animator = animator;
}
}
모든 상태 클래스가 공통으로 사용할 필드(플레이어, 애니메이터)를 제공한다.
이렇게 해주면 상태별로 공통 코드를 줄이고 중복을 방지할 수 있다.
2. Idle 상태 / 플레이어 컨트롤러
public class PlayerStateIdle : PlayerState, IPlayerState
{
public PlayerStateIdle(PlayerController playerController, Animator animator)
: base(playerController, animator) { }
public void Enter() { /* Idle 애니메이션 재생 */ }
public void Update() { /* 가만히 있기 */ }
public void Exit() { /* 상태 빠져나갈 때 처리 */ }
}
PlayerState와 IPlayerState를 상속받아
캐릭터와 애니메이터를 불러와주고, 필수로 구현해야할 인터페이스를 넣어준다.
지금은 빈 메서드이지만 여기에 animator.SetTrigger("Idle") 같은 로직을 넣을 것으로 예상된다.
public class PlayerController : MonoBehaviour
{
private Animator _animator;
private PlayerInput _playerInput;
public EPlayerState State { get; private set; }
private Dictionary<EPlayerState, IPlayerState> _states;
private void Awake()
{
_animator = GetComponent<Animator>();
_playerInput = GetComponent<PlayerInput>();
var playerStateIdle = new PlayerStateIdle(this, _animator);
_states = new Dictionary<EPlayerState, IPlayerState>
{
{ EPlayerState.Idle, playerStateIdle },
};
SetState(EPlayerState.Idle);
}
private void Update()
{
if (State != EPlayerState.None)
{
_states[State].Update();
}
}
public void SetState(EPlayerState state)
{
if (State == state) return;
if (State != EPlayerState.None) _states[State].Exit();
State = state;
if (State != EPlayerState.None) _states[State].Enter();
}
}
Animator와 PlayerInput 컴포넌트를 자동으로 가져온다
상태 전환은 SetState()로만 하도록 해서 깨끗한 흐름을 보장한다.
public class EllenPlayerController : PlayerController { }
Ellen 캐릭터 전용 클래스이다.
이렇게 하면 한 캐릭터에만 특별한 기능을 넣을 수 있다.
2. 커스텀 인스펙터
유니티의 Custom Editor 기능을 활용해서
특정 컴포넌트가 Inspector 창에 어떻게 표시될지를 커스터마이징 하는 스크립트를 작성해주려고 한다.
1. 기본 구조
[CustomEditor(typeof(EllenPlayerController))]
public class PlayerControllerEditor : Editor
기존에 늘 상속받던 MonoBehaviour가 아니라 Editor를 상속받아 Unity 에디터 전용 스크립트를 생성해 준다.
[CustomEditor(typeof(EllenPlayerController))] 해당 명령어로 인해
해당 클래스는 Inspector에서 EllenPlayerController 컴포넌트를 볼 때에만 작동한다.
즉, 일반적으로 Unity에서 public이나 [SerializeField]로 변수만 Inspector에 보이지만