목차
상태 패턴
상태 패턴은 유한 상태를 관리할 때 보통 사용하는 패턴입니다.
예를 들어 캐릭터를 구현할 때, 캐릭터의 상태에 따라 변하는 상태 동작을 구현할 수 있는 패턴이 바로 상태 패턴입니다.
상태 패턴 개요
Context : 클라이언트가 객체의 내부 상태를 변경할 수 있도록 요청하는 인터페이스를 정의합니다. 또한 현재 상태의 포인터(state)를 보유하고 있습니다.
State 인터페이스 : 구체적인 상태 클래스로 연결할 수 있도록 설정합니다.
State 클래스 : State인터페이스를 상속받고 State 인터페이스의 메소드들을 구현합니다.
오토바이 상태 패턴 정의
오토바이 상태 패턴을 유한 상태로 다이어그램과 그에 따른 정의를 설명하겠습니다.
정지 : 오토바이가 움직이지 않습니다.
시작 : 오토바이는 최고 속도로 움직이기 시작합니다.
회전 : 오토바이는 플레이어의 입력에 따라 왼쪽이나 오른쪽으로 회전합니다.
충돌 : 오토바이가 충돌 상태라면, 오토바이가 삭제 됩니다.
오토바이 상태 패턴 인터페이스와 Context 구현하기
State 인터페이스
public interface IBikeState
{
void Handle(BikeController controller);
}
C#
복사
모든 오토바이 State 클래스가 상속하게 될 State 인터페이스입니다. Handle 메소드를 구현해야하며, Handle 메소드는 BikeController 인스턴스를 전달합니다.
Context 클래스
public class BikeStateContext
{
public IBikeState CurrentState
{
get; set;
}
private readonly BikeController _bikeController;
public BikeStateContext(BikeController bikeController)
{
_bikeController = bikeController;
}
public void Transition()
{
CurrentState.Handle(_bikeController);
}
public void Transition(IBikeState state)
{
CurrentState = state;
CurrentState.Handle(_bikeController);
}
}
C#
복사
CurrentState : 현재 상태를 나타냅니다.
_bikeController : 현재 객체입니다.
Transition() : 현재 스테이트에 따라 _bikeController를 전환합니다.
Transtion(IBikeState state) : 현재 스테이트를 state로 변경하고 그에 따라 bikeController를 전환합니다.
오토바이 상태 구현하기
정지 State 클래스
public class BikeStopState : MonoBehaviour, IBikeState
{
private BikeController _bikeController;
public void Handle(BikeController bikeController)
{
if (!_bikeController)
_bikeController = bikeController;
_bikeController.CurrentSpeed = 0;
}
}
C#
복사
오토바이가 정지 상태라면 현재 속도를 0으로 변경합니다.
public class BikeStartState : MonoBehaviour, IBikeState
{
private BikeController _bikeController;
public void Handle(BikeController bikeController)
{
if (!_bikeController)
_bikeController = bikeController;
_bikeController.CurrentSpeed = 100f;
}
}
C#
복사
오토바이가 이동 상태라면, 현재 속도를 100f로 변경합니다.
public class BikeTurnState : MonoBehaviour, IBikeState
{
private Vector3 _turnDirection;
private BikeController _bikeController;
public void Handle(BikeController bikeController)
{
if (!_bikeController)
_bikeController = bikeController;
// 회전 변경 코드
_bikeController.Direction = 변경된 회전
}
}
C#
복사
오토바이가 회전 상태라면, 회전하는 방향에 맞춰 Direction을 변경합니다.
public class BikeCollisionState : MonoBehaviour, IBikeState
{
public void Handle(BikeController bikeController)
{
if (!_bikeController)
_bikeController = bikeController;
Destroy(_bikeController.gameObject);
}
}
C#
복사
오토바이가 충돌 상태라면, 오토바이는 삭제됩니다.
상태 패턴의 장단점
장점
1.
캡슐화 : 상태 패턴은 상태가 변할 때, 개체에 동적으로 할당할 수 있는 컴포넌트 집합입니다. 개체의 상태별 행동을 캡슐화하여 구현할 수 있습니다.
2.
유지 및 관리 : 긴 조건문이나 방대해진 클래스의 수정 없이도 쉽게 새로운 상태를 구현할 수 있습니다.
단점
사실 단점이라기 보다는, 아래 내용은 상태 패턴만으로 구현할 수 없는 한계입니다.
1.
블렌딩 : 기본 형태에서 상태 패턴은 애니메이션 블렌드 방법은 제공하지 않습니다.
ㄴ 위 방법은 캐릭터 애니메이션 전환시 블렌딩하는 요소를 넣어주면 됩니다.
ㄴ 예를 들어 Spine 애니메이션으로 구현할 경우, 스파인 애니메이션 전환에 있어 블렌딩 요소를 넣어주면 되겠죠.
2.
전환 : 이전 상태와 다음 상태를 이어주는 상태 전환은 현재 상태 패턴만으로 구현하긴 어렵습니다. 예를 들어, 정지 중 점프 모션과 이동 중 점프 모션은 차이가 발생할 수 있습니다.
ㄴ 이러한 부분들은 다른 패턴을 병합하여 해결할 수 있습니다.