
유한 상태 머신은 특정 개수의 상태(State)와 상태전이로 구성된 모델이다.
하나의 상태에서 정해진 규칙에 대해 다른 상태로 전환 될 수 있다.
이는 유니티에서의 캐릭터의 상태의 관리, AI의 구현에 사용된다.
유니티에서 게임의 로직을 관리하려면 여러 개의 상태가 있고 이에 따른 처리가 필요하다.
예를 들어 서기, 점프, 엎드리기의 상태가 있다고 가정하고 입력에 따라 각각의 처리를 한다면
서 있는 경우에는 스페이바를 누르면 점프가 가능하다고 하면 이를 관리하는 변수를 추가하고 관리해야한다
엎드리기 기능은 아래 버튼을 누르면 작동한다면 이를 위해서는 현재 상태가 서기인지 확인하고 입력을 처리하는 필요가 있다.
지금은 3개의 상태의 사이를 관리하는데에도 고려해야할 사앙이 늘어나며
여기서 점프중에 이중 점프나 점프중의 공격을 추가한다면 새로운 변수와 입력에 대한 처리를 추가해야 된다. 이러한 추가가 점점 쌓이면 가독성이 떨어져 한눈에 어떻게 변하는지 알 수 없으며 상태간의 이동도 관리하기 어려울 것이다.
이를 개선하기 위해 유한 상태 머신을 사용한다.
public interface IState
{
public void Enter();
public void Exit();
public void Update();
public void FixedUpdate();
}
객체의 상태는 위의 IState를 상속 받고 이를 객체에서 가상함수로 만들고 각각의 상태에서 이를 구현한다.
public override void Enter()
{
base.Enter();
...
}
public override void Exit()
{
base.Exit();
...
}
public override void FixedUpdate()
{
base.FixedUpdate();
...
}
각 상태(State)는 위와 같이 각 상태의 행동을 직접 구현할 필요가 있다.
예를 들어 애니메이션의 SubStateMachine처럼 상위상태와 하위 상태가 있다면 이를 전부 새로운 State로 만들어야한다. 또한 각각의 상태는 구현이 필요하다.
이를 위해 상태 머신은 다음과 같은 기본 구조를 갖는다.
public abstract class StateMachine
{
protected IState currentState;
public void ChangeState(IState newState)
{
currentState?.Exit();
currentState = newState;
currentState.Enter();
}
public void Update()
{
currentState?.Update();
}
public void FixedUpdate()
{
currentState?.FixedUpdate();
}
}
상태는 머신은 현재의 상태의 함수를 호출한다.
상태가 변할 때는 현재 Exit()를 호출하고 상태를 변경하고 새로운 상태의 Enter()를 실행한다.
이후 내부 로직에 따라 Update()나 FixedUpdate() 호출하여 각 상태의 동작을 실행한다.
이를 위해서는 StateMachine을 상속받아 사용한다.
플레이어라면 플레이러의 상태머신을, 몬스터라면 몬스터의 상태 머신을 개별로 작성한다.
그리고 또한 실제 사용을 위해서는 다음과 같이 사용한다.
public class PlayerStateMachine : StateMachine
{
public PlayerIdlingState IdlingState { get; }
public PlayerDashingState DashingState { get; }
public PlayerStateMachine(PlayerHandler player)
{
Player = player;
ReusableData = new PlayerStateReusableData();
IdlingState = new PlayerIdlingState(this);
DashingState = new PlayerDashingState(this);
}
}
최상위인 상태 머신에서 각 상태를 변수를 가지고 생성자를 통해 초기화한다.
이를 통해 다음과 같이 사용한다.
stateMachine.ChangeState(stateMachine.IdlingState);
하위의 상태 혹은 객체에서 상태머신의 상태로 상태를 간단히 바꿀 수 있도록한다.
상태 머신을 사용하면 상태를 추가하거나 삭제할 경우의 수정이 적어지고 관리 변수와 상태의 이동을 한눈에 보기 좋다는 장점이 있다. 기본 구조를 만드는것이 오래 걸리지만 확장성이 매우 높아 변동이 클 경우 유용하게 쓸 수 있다.