상태 패턴이다.
오히려 고전적인 구현에 더 많이 쓰이는 듯하다.
회로라던지 통신의 로우 레이어라던지.
상태 패턴도 요즘은 좀 남발되는 경우가 많은 것 같다.
AI가 대두되고, 이것이 게임에 적용되기 시작하면서 더더욱 그런 것 같다.
유한 상태 기계 (FSM, Finite State Machine)
유한 상태 기계는 상태와 상태 간의 전환을 기반으로 동작하는 동작 기반 시스템이다.
이렇게만 이야기 하면 감이 잘 오지 않는데, 이런 상황을 구해야 한다고 해보자.
청기백기 게임인데, 아래-중간-위가 있다고 해보면 다음 그림의 느낌이 될 것이다.
이 때, 상태 패턴 없이 구현을 해본다 치면?
switch (명령) {
case (청기올려):
if (청기 == 아래) 청기 = 중간;
else if (청기 == 중간) 청기 = 위;
break;
case (청기내려):
if (청기 == 중간) 청기 = 아래;
else if (청기 == 위) 청기 = 중간;
break;
case (백기올려):
if (백기 == 아래) 백기 = 중간;
else if (백기 == 중간) 백기 = 위;
break;
case (백기내려):
if (백기 == 중간) 백기 = 아래;
else if (백기 == 위) 백기 = 중간;
break;
// ...
}
벌써부터 마음에 안들지 않은가?
왜냐면, 사실 이걸 그림으로 그리면 그냥 이렇게 만들 수 있지 않은가?
그림이 다소 번잡스럽지만, 이해 바란다.
오히려 이렇게 설계하는 것이 더 직관적이지 않은가?
예상 했겠지만 위의 그림으로 나타낸 것이 바로 유한상태머신(FSM)이다.
FSM의 구성 요소는 보통 다음과 같이 구성된다.
- 상태 (State): 시스템이 취할 수 있는 다양한 상태를 나타냄
- 전환 조건 (Transition Condition): 상태 간 전환을 결정하는 조건
- 동작 (Action): 상태에 따라 수행되는 동작 또는 로직
상태 패턴의 구현
보통은 인터페이스를 이용하여 구현한다.
public interface IState
{
public void Enter();
public void Exit();
public void HandleInput();
public void Update();
public void PhysicsUpdate();
}
public abstract class StateMachine
{
protected IState currentState;
public void ChangeState(IState newState)
{
currentState?.Exit();
currentState = newState;
currentState?.Enter();
}
public void HandleInput()
{
currentState?.HandleInput();
}
public void Update()
{
currentState?.Update();
}
public void PhysicsUpdate()
{
currentState?.PhysicsUpdate();
}
}
위의 기본적인 형태를 바탕으로 이를 상속 받아 다양한 상태를 만든다.
이전 게시글에 FSM을 이용하여 플레이어 이동을 구현하는 글이 있으니 그것을 링크하겠다.
여기서 만약 추가로 몇 가지의 상태를 더 추가하고 싶다면 기존 상태의 코드 변경 없이 추가해줄 수 있는 것이다.
우리는 이미 상태 패턴을 알고 있다
사실 지금까지 열심히 상태 패턴의 예시를 구현해봤지만, 사실 유니티 내 기능 중에 이미 상태 패턴으로 구현된 것이 있다.
바로 애니메이터 (Animator) 이다.
해당 애니메이터가 바로 상태 패턴으로 구현된 것이다!
상태 패턴의 형태
기본적으로 현재 상태 (State) 에 따른 동작 (Action) 과 상태 간을 넘나들기 위한 조건으로 이루어져 있다고 언급했다.
구조 자체가 제한되어 있기 때문에 코드는 매우 깔끔하지만, 새로 무언가를 추가하려고 해도 상태형으로만 추가해줄 수가 있는 것이다.
책에서는 FSM을 좀더 광범위하게 적용할 수 있게 하기 위해 다음과 같은 형태를 소개하고 있다.
병행 상태 기계
: 한 클래스가 하나의 상태를 참조하는 것이 아닌 여러 개를 참조하는 것이다. 위의 청기 백기에서 청기, 백기 상태를 각각 두는 것이라고 생각하면 좋다.
계층형 상태 기계
: 어떤 상태는 상위 상태 (Superstate) 이고 그 상위 상태에 속하는 하위 상태 (Substate)를 가질 수 있다. 위에서 링크한 FSM으로 플레이어 이동을 구현할 때 GroundState / AirState로 상위 상태를 나누고, GroundState는 IDLE, MOVE와 같이 하위 상태를 나누는 것이 그 예이다.
푸시다운 오토마타
: 진입하는 State를 전부 스택에 저장하여 스택의 Top을 현재 상태로 삼는 오토마타이다. 이렇게 하면 이전의 상태를 저장하고, 그 이전의 상태로 돌아가는 짓이 가능해진다.
언제 사용하는가?
FSM을 보통 언제 사용하는가?
보통은 위의 예시처럼 다음 동작을 하기 위해 오브젝트의 “현재 상태”가 필요한 상황일 때 쓰면 모델링이 매우 편해진다.
책에서는 다음과 같이 정리하고 있다.
- 내부 상태에 따라 객체 동작이 바뀔 때
- 이런 상태가 그다지 많지 않은 선택지로 분명하게 구분될 수 있을 때
- 객체가 입력이나 이벤트에 따라 반응할 때
입력 처리나 메뉴 화면 전환, 문자 해석, 네트워크 프로토콜, 비동기 동작 등에 제일 많이 사용된다.
AI에서는 요즘 생각보다 FSM을 광범위하게 사용하지는 않는다.
시작부분에 언급했듯 요즘 게임의 AI는 행동 트리 (Behaviour Tree) 나 계획 시스템 (Planning System) 을 더 많이 쓴다고 한다.
Uploaded by N2T
'개발 > 게임 디자인 패턴' 카테고리의 다른 글
게임 디자인 패턴 8. 하위 클래스 샌드박스 (Subclass Sandbox Pattern) (1) | 2023.11.01 |
---|---|
게임 디자인 패턴 7. 이중 버퍼 패턴 (Double Buffer Pattern) (0) | 2023.10.31 |
게임 디자인 패턴 5. 싱글턴 패턴 (Singleton Pattern) (1) | 2023.10.27 |
게임 디자인 패턴 4. 프로토타입 (Prototype) (0) | 2023.10.26 |
게임 디자인 패턴 3. 관찰자 패턴 (Observer Pattern) (0) | 2023.10.25 |