FSM(Finite State Machine, 유한 상태 기계)
게임 오브젝트의 상태를 체계적으로 관리하고 전환하기 위한 설계 패턴
플레이어나 적 AI처럼 상태에 따라 행동이 달라지는 시스템에 자주 사용
사용하는 이유
코드의 가독성과 유지보수성 향상
→ 상태별 로직을 분리해서 각 클래스나 메서드에 구현 가능.
복잡한 조건 분기를 명확하게 구조화
→ if-else나 switch 남발 대신 상태 전이 중심 설계.
확장성과 재사용성 좋음
→ 새로운 상태 추가 및 전이 조건 설정이 쉬움.
IState (상태 인터페이스)
// 상태 인터페이스
public interface IState
{
void Enter();
void Execute();
void Exit();
}
역할
모든 상태들이 따라야 할 공통 규칙을 정의
각 상태는 이 인터페이스를 구현(implements)하여, 상태 진입, 유지, 종료 시의 동작을 정의함
IdleState, WalkState 등 (상태 클래스들)
// Idle 상태
public class IdleState : IState
{
public void Enter()
{
Debug.Log("Idle: Enter");
}
public void Execute()
{
Debug.Log("Idle: Execute");
}
public void Exit()
{
Debug.Log("Idle: Exit");
}
}
// Walk 상태
public class WalkState : IState
{
public void Enter()
{
Debug.Log("Walk: Enter");
}
public void Execute()
{
Debug.Log("Walk: Execute");
}
public void Exit()
{
Debug.Log("Walk: Exit");
}
}
역할
실제 상태별 동작을 정의하는 클래스
Enter()에선 애니메이션 시작이나 초기화,
Execute()에선 반복 동작(예: 걷기),
Exit()에선 상태 전환 전 정리 작업 등을 수행
StateMachine
public class StateMachine
{
private IState currentState;
public void ChangeState(IState newState)
{
currentState?.Exit();
currentState = newState;
currentState.Enter();
}
public void Update() // 생명주기 함수 Update 아님 주의(Execute로 이름 대체 가능)
{
currentState.Execute();
}
}
역할
현재 상태를 기억하고,
새로운 상태로 전이(change)하며,
현재 상태의 로직을 실행(update)하는 중앙 관리자입니다.
즉, 상태 전환과 실행을 통제하는 컨트롤 타워 역할
왜 필요할까?
상태 객체만으로는 전환(변경)을 스스로 못함 → 누군가가 상태를 [관리]해줘야 함
StateMachine이 없으면, 상태끼리 서로 직접 호출해야 해서 코드가 복잡하고 꼬이게 됨
상태 전환을 일관되고 안전하게 처리할 수 있음
Player (FSM을 사용하는 MonoBehaviour)
public class Character : MonoBehaviour
{
private StateMachine stateMachine;
private void Start()
{
stateMachine = new StateMachine();
stateMachine.ChangeState(new IdleState());
}
private void Update()
{
stateMachine.Update();
if (Input.GetKeyDown(KeyCode.W))
{
stateMachine.ChangeState(new WalkState());
}
else if (Input.GetKeyDown(KeyCode.I))
{
stateMachine.ChangeState(new IdleState());
}
}
}
HFSM이란?
HFSM (Hierarchical Finite State Machine) 은 기존 FSM보다 한 단계 더 진화된 형태
FSM (Finite State Machine) | HFSM (Hierarchical FSM) |
모든 상태가 동등한 계층 | 상태가 상위/하위 계층 구조 |
상태 전환만 있음 | 하위 상태, 공통 동작, 상속 구조 가능 |
예: Idle, Walk, Jump | 예: Ground → Idle, Walk (하위 상태) |
캐릭터 상태 예시
[GroundState] ← 상위 상태 (공통 로직: 중력, 점프 감지 등)
├── [IdleState] ← 멈춰 있을 때
└── [WalkState] ← 이동 중일 때
[AirState] ← 공중 상태 (점프 중, 낙하 중)
├── [JumpState]
└── [FallState]
IState (상태 인터페이스)
public interface IState
{
void Enter();
void Exit();
void HandleInput();
void LogicUpdate();
void PhysicsUpdate();
}
IdleState (GroundState 상속)
public class PlayerIdleState : PlayerGroundState
{
public PlayerIdleState(PlayerStateMachine playerStateMachine) : base(playerStateMachine)
{
}
public override void Enter()
{
stateMachine.MovementSpeedModifier = 0f;
base.Enter();
StartAnimation(stateMachine.Player.AnimationData.IdleParameterHash);
}
public override void Exit()
{
base.Exit();
StopAnimation(stateMachine.Player.AnimationData.IdleParameterHash);
}
public override void Execute()
{
base.Execute();
}
}
PlayerStateMachine
public class PlayerStateMachine : StateMachine
{
public Player Player { get; }
public Vector2 MovementInput { get; set; }
public float MovementSpeed { get; private set; }
public float RotationDamping { get; private set; }
public float MovementSpeedModifier { get; set; } = 1f;
public float JumpForce { get; set; }
public Transform MainCameraTransform { get; set; }
public PlayerIdleState IdleState { get; private set; }
public PlayerStateMachine(Player player)
{
this.Player = player;
IdleState = new PlayerIdleState(this);
...중략
}
}
PlayerStateMachine은 플레이어 전용 FSM으로
입력값, 속도, 점프력 등 캐릭터 제어에 필요한 데이터를 저장
IdleState 정보를 가지고 있음으로서 StateMachine에 상태(ChageState)에 접근할 수 있음
Player
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour // 입력 뿐만 아니라 여러가지 컴포넌트 관리해주는 클래스
{
...중략
private PlayerStateMachine stateMachine;
void Awake()
{
...중략
stateMachine = new PlayerStateMachine(this);
stateMachine.ChangeState(stateMachine.IdleState);
}
... 중략
private void Update()
{
stateMachine.HandleInput();
stateMachine.Execute();
}
private void FixedUpdate()
{
stateMachine.PhysicsExecute();
}
}
'Unity > 디자인 패턴' 카테고리의 다른 글
전략 패턴 (0) | 2025.05.04 |
---|---|
싱글톤 패턴 (0) | 2025.05.02 |
오브젝트 풀링 패턴 (0) | 2025.03.08 |