포스트

[Unity] 스테이트 머신 구현

[Unity] 스테이트 머신 구현

Unity 상태머신(State Machine) 구현 예시

1. 상태머신 개념

  • 상태(State): 객체가 가질 수 있는 상태 (예: Idle, Move, Attack)
  • 상태 전이(Transition): 상태가 다른 상태로 전환되는 규칙
  • 상태별 로직: 각 상태마다 독립적으로 동작 수행

2. 상태머신 기본 구조 (클래스 기반)

2.1 상태 인터페이스 정의

1
2
3
4
5
6
public interface IState
{
    void Enter();
    void Execute();
    void Exit();
}

모든 상태는 Enter(), Execute(), Exit() 메서드를 포함.


2.2 상태 구현 클래스

1
2
3
4
5
6
7
8
9
10
11
12
13
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"); }
}

public class MoveState : IState
{
    public void Enter() { Debug.Log("Move: Enter"); }
    public void Execute() { Debug.Log("Move: Execute"); }
    public void Exit() { Debug.Log("Move: Exit"); }
}

각 상태마다 동작 정의.


2.3 상태머신 관리 클래스

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class StateMachine
{
    private IState currentState;

    public void ChangeState(IState newState)
    {
        if (currentState != null)
            currentState.Exit();

        currentState = newState;

        if (currentState != null)
            currentState.Enter();
    }

    public void Update()
    {
        if (currentState != null)
            currentState.Execute();
    }
}

ChangeState()로 상태 변경, Update()로 현재 상태 실행.


2.4 Unity 컴포넌트 연결

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
using UnityEngine;

public class Enemy : MonoBehaviour
{
    private StateMachine stateMachine;

    private void Start()
    {
        stateMachine = new StateMachine();
        stateMachine.ChangeState(new IdleState());
    }

    private void Update()
    {
        stateMachine.Update();

        if (Input.GetKeyDown(KeyCode.Space))
        {
            stateMachine.ChangeState(new MoveState());
        }
    }
}

3. 실행 결과

  1. 게임 시작 시 "Idle: Enter" 출력
  2. 매 프레임 "Idle: Execute" 출력
  3. 스페이스바 누르면:

    • "Idle: Exit"
    • "Move: Enter"
    • 이후 매 프레임 "Move: Execute" 출력

4. 구조 요약

1
2
3
4
5
Enemy (MonoBehaviour)
 └ StateMachine
     ├ IState (interface)
     ├ IdleState
     └ MoveState

5. 이 방식의 장점

  • 상태 추가/수정 시 클래스만 추가하면 됨
  • 각 상태 코드가 독립적 (SRP 원칙 만족)
  • 상태 전이 로직이 명확하고 깔끔

6. 대안 방법

더 복잡하거나 시각적 상태머신 필요 시:

  • Unity Animator + Animation State Machine 사용
  • Unity Visual Scripting
  • PlayMaker 같은 3rd Party FSM Asset 사용



Unity 상태머신 구현 방식 비교 (클래스 기반 vs enum 기반)

1. 기본 개념

방식설명
클래스 기반각 상태를 별도의 클래스로 정의
enum 기반상태를 enum 값으로 구분, 상태마다 분기문 작성

2. 코드 구조 예시

클래스 기반 예시

1
2
3
4
5
6
interface IState { void Enter(); void Execute(); void Exit(); }
class IdleState : IState { ... }
class MoveState : IState { ... }

StateMachine.ChangeState(new IdleState());
StateMachine.Update(); // 현재 상태의 Execute() 실행
  • 상태마다 독립 클래스 + 메서드 호출

enum 기반 예시

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
enum State { Idle, Move }
State currentState;

void Update()
{
    switch (currentState)
    {
        case State.Idle:
            // Idle 로직
            break;
        case State.Move:
            // Move 로직
            break;
    }
}
  • switch 문 안에 상태별 로직 작성

3. 주요 차이점

항목클래스 기반enum 기반
상태 확장성✔ 클래스 추가만 필요❌ switch-case 수정 필요
상태 코드 분리✔ 각 상태 클래스 별도 파일❌ 모든 상태 로직 한 파일에 작성
유지보수성✔ 각 상태 독립 → 영향 적음❌ 상태 늘어날수록 switch 복잡
초보자 이해❌ 추상화 개념 필요✔ 직관적이고 간단함
실행 속도거의 동일 (최적화 영향 미미)거의 동일
다형성 (override)✔ OOP 다형성 지원❌ 불가능

4. enum 기반이 적합한 경우

  • 상태 개수가 적고 간단할 때
  • 간단한 상태 전이만 필요할 때
  • 프로토타입, 테스트 코드 작성

예: Idle, Move, Attack 정도의 간단한 상태


5. 클래스 기반이 적합한 경우

  • 상태마다 복잡한 로직 포함
  • 상태별 Enter, Execute, Exit 메서드 필요
  • 상태 추가/삭제/수정이 자주 일어날 때
  • 상태를 다른 객체에서도 재사용해야 할 때

예: 적 AI, 플레이어 상태, 보스 패턴 관리


6. 예시 비교

클래스 기반 상태 전환

1
stateMachine.ChangeState(new MoveState());

MoveState.Enter(), MoveState.Execute(), MoveState.Exit() 자동 관리

enum 기반 상태 전환

1
2
currentState = State.Move;
switch (currentState) { case State.Move: ... }

→ 상태별 진입/종료 로직 직접 호출 필요


7. 추천 상황 요약

상황추천 방식
상태 개수 적고 간단enum 기반
상태 많고 복잡클래스 기반
유지보수성, 확장성 중시클래스 기반
빠른 구현, 프로토타입enum 기반

결론:

  • 클래스 기반 → 확장성과 유지보수성
  • enum 기반 → 간단함과 빠른 작성
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.