
2024-06-26

FSM (Finite State Machine) 는 상태를 기반으로 동작을 제어하는 방식의 디자인 패턴이다.
구글링과 유튜브를 통해, 크게 2가지의 FSM 활용 방법을 찾아보았다.
Idle, Chase , Attack 3가지 상태가 존재하는 Enemy FSM 으로 예시를 들어보자.
public enum State
{
Idle,
Chase,
Attack
}
public State curState = State.Idle;
IEnumerator FSM()
{
yield return null;
while(hp > 0)
{
yield return StartCoroutine(curState.ToString());
}
}
IEnumerator Idle()
{
yield return null;
Anim.SetBool("idle",true);
if ( 조건1 )// Enemy 가 플레이어를 발견했을 경우
{
if( 조건2 ) // 공격 가능한 경우
curState = State.Attack;
else // 공격 불가능한 경우
curState = State.Chase;
}
else // Enemy 가 플레이어를 발견하지 못한 경우
curState = State.Idle;
}
IEnumerator Chase()
{
yield return null;
Anim.SetBool("chase",true);
// Enemy 가 플레이어 쪽으로 이동하는 로직
if( 조건1 ) // Enemy 가 플레이어를 공격 가능한 경우
curState = State.Attack;
else // Enemy 가 플레이어를 공격할 수 없는 경우
curState = State.Chase;
if ( 조건2 ) // Enemy 가 플레이어를 놓친 경우
curState = State.Idle;
}
IEnumerator Attack()
{
yield return null;
Anim.SetTrigger("attack");
// Enemy 가 플레이어를 공격하는 로직
if( 조건1 ) // 플레이어가 여전히 Enemy 의 탐지 범위에 있는 경우
curState = State.Chase;
else // 플레이어가 Enemy 의 탐지 범위에서 벗어난 경우
curState = State.Idle;
}
위에서 언급한 4가지 구성요소가 모두 적절히 사용되었다.
Idle, Chase, Attack 의 3가지의 State ,
Event 에 따른 Transition , 상태마다 수행되는 Action.
// BaseState 라는 추상 클래스를 정의하고,
// 각 상태를 구현하기 위한 필수적인 내용을 미리 정의한다.
public abstract class BaseState
{
protected Enemy enemy;
protected BaseState(Enemy enemy)
{
this.enemy = enemy;
}
public abstract void EnterState(); // 상태 진입 시, 초기화
public abstract void Update(); // 매 프레임마다 호출
public abstract void ExitState(); // 상태 변경 시, 초기화
}
public class IdleState : BaseState
{
public IdleState(Enemy enemy) : base(enemy) { }
public override void EnterState()
{
// Idle 상태 진입 시, 초기화 로직
}
public override void Update()
{
// Ex : 플레이어 탐지 로직
}
public override void ExitState()
{
}
}
public class ChaseState : BaseState
{
public ChaseState(Enemy enemy) : base(enemy) { }
public override void EnterState()
{
// Chase 상태 진입 시, 초기화 로직
}
public override void Update()
{
// Ex : 플레이어 방향으로 이동 , 공격 범위 안 타겟 탐지
}
public override void ExitState()
{
}
}
public class AttackState : BaseState
{
public AttackState(Enemy enemy) : base(enemy) { }
public override void EnterState()
{
// Attack 상태 진입 시, 초기화 로직
}
public override void Update()
{
// Ex : 플레이어 공격 로직
}
public override void ExitState()
{
}
}
FSM 의 두 가지 구현 방법에 대해 알아보며, 각각의 장점에 대해 알아보았다.
다양한 방법으로 FSM 을 구현해보며, 상황에 따라 적절한 구현 방식을 활용해야겠다.