본문 바로가기
유니티 공부/Unity

Unity - FSM(Finite State Machine)을 사용해서 몬스터 AI를 만들어보자

by 코딩하는 돼징 2025. 5. 9.
반응형

FSM이란?

FSM은 프로그램에서 객체의 행동을 여러 상태(State)로 나누고 현재 상태에 따라 객체의 행동을 다르게 설정하는 설계 패턴이다. 

예시 : Idle → 플레이어 발견 → Chase → 공격 범위 안 → Attack


FSM 핵심 구성 요소

1. 상태(State) - 객체의 행동 단위,  각 상태는 독립적인 로직을 가짐

2. 전이(Transition) - 특정 조건이 만족되면 상태 변경 발생

3. 상태 머신(StateMachine) - 현재 상태 추적 및 전이 관리

4. State Owner(상태 주체) - FSM을 실행하는 객체

사장(State Owner) vs 직원(State)  vs 회사(StateMachine)


01 사장(State Owner)  

FSM을 사용하는 주체 ex) 적 AI

상태를 바꾸고 싶으면 자신의 FSM인스턴스에 요청

public class EnemyController<T> : MonoBehaviour, IStateMachineOwner<T>
{
     protected StateMachine<T> _fsm = new StateMachine<T>();

    void Start()
    {

        ChangeState(new IdleState());
    }

    void Update()
    {
        _fsm.Update(this as T);
    }

    public void ChangeState(IState<T> _currentState)
    {
        _fsm.ChangeState(_currentState, this as T);
    }
}

IStateMachineOwner<T>이 왜 필요할까?

상태 내부에서 아래처럼 상태 전이를 하고 싶을 때 문제가 발생한다.

public class ChaseState : IState<T> // T = EnemyController
{
    public void Update(T owner)
    {
        owner.ChangeState(new AttackState()); // 오류 발생 가능
    }
}

여기서 T는 제네릭이기 때문에 ChangeState가 존재한다는 걸 보장할 수 없다. 그래서 컴파일 에러가 발생할 수 있다.

 

그래서 IStateMachineOwner가 필요하다. 이렇게 하면 타입안전성이 보장된다.

 


02 직원(State)

실제 업무를 수행하는 객체이다. 보통 Enter, Update, Exit 메서드를 가진다.

public interface IState<T>
{
    void Enter(T obj);
    void Update(T obj);
    void Exit(T obj);
}

03 회사(StateMachine)

현재 어떤 직원(State)이 일하고 있는지 관리한다. Update가 매 프레임 호출되며 현재 상태의 Update를 대신 호출한다. 상태가 바뀌면 Exit() → Enter순서대로 호출된다.

public class StateMachine<T>
{
    private IState<T> _cuurentState;

    // state바뀔때 기존꺼 나가고 새로운거 enter
    public void ChangeState(IState<T> newState, T obj)
    {
        _cuurentState?.Exit(obj);
        _cuurentState = newState;
        _cuurentState?.Enter(obj);
    }

    public void Update(T obj)
    {
        _cuurentState?.Update(obj);
    }
}

구조 시각화

EnemyController (사장)
  └── StateMachine<EnemyController> (회사)
         ├── IdleState : IState<EnemyController> (직원)
         ├── ChaseState : IState<EnemyController>
         └── AttackState : IState<EnemyController>

 

 

반응형

댓글