| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 | 31 |
- 추상 팩토리 패턴
- 기술면접
- New Input System
- MVP 패턴
- C#
- 프로젝트 생성
- Visual Studio Installer
- Abstract Factory Pattern
- 구글플레이콘솔
- 게임 디자인 패턴
- 오브젝트 풀
- 유니티
- unity
- Dependency Injection
- Di
- 콘솔 앱
- Unity 기술면접
- 의존성 주입
- 개발
- Canvas Scaler
- Object Pool
- 데이터 형식
- 구글 스프레드 시트
- 테이블 데이터
- event bus
- Render Mode
- 상태 패턴
- github desktop
- 이벤트 버스
- 스타일 지침
- Today
- Total
DevDino
[게임 디자인 패턴] 상태 패턴(State Pattern) 본문
State Pattern
게임을 개발하다 보면 캐릭터나 몬스터의 행동을 제어하기 위해 수많은 상태(대기, 걷기, 뛰기, 사망 등)를 구현하게 됩니다.
Update문 안에서 조건을 나누어 사용하는 것은 쉽고 편하지만, 프로젝트가 커질수록 코드는 끝없는 스파게티처럼 꼬이게 됩니다.
이런 복잡한 조건문 지옥에서 벗어나 코드를 깔끔하고 확장하기 쉽게 만들어주는 상태 패턴(State Pattern)에 대해 알아보겠습니다.
상태 패턴(State Pattern)이란?
상태 패턴은 객체의 내부 상태가 바뀔 때 행동을 변경할 수 있도록 하는 디자인 패턴입니다. 쉽게 말해, '상태' 자체를 하나의 클래스로 분리하여 관리하는 방법입니다.
기존에는 플레이어 스크립트 하나에서 모든 상태를 통제했다면, 상태 패턴을 적용하면 '대기 상태 클래스', '이동 상태 클래스'가 각각 자신의 행동만 책임지게 됩니다.
상태 패턴의 장점
- 코드의 가독성 향상: if~else문이 사라져 코드가 훨씬 깔끔해집니다.
- 유지보수 및 확장성 증가: 새로운 상태를 추가할 때 기존 코드를 수정할 필요 없이 새로운 클래스만 추가하면 됩니다(단일 책임 원칙 준수).
- 버그 감소: 상태 전환 로직이 명확해져서 예상치 못한 상태 중첩 버그를 줄일 수 있습니다.
구현 예제
상태 패턴을 유니티에 적용하기 위해 크게 3가지 요소가 필요합니다.
1. IState(인터페이스): 모든 상태가 공통으로 가질 메서드를 정의합니다.
2. Context(상태 관리자): 현재 상태를 가지고 있으며, 상태 전환을 실행합니다.
3. Concrete States(구제적인 상태들): IState를 상속받아 실제로 동작을 구현하는 클래스들입니다.
1. IState 인터페이스 정의하기
가장 먼저 모든 상태 클래스가 지켜야 할 규칙(인터페이스)을 만듭니다. 보통 상태에 진입할 때, 머무를 때, 빠져나갈 때의 3가지 행동을 정의합니다.
public interface IState
{
// 상태에 진입할 때 한 번 호출됩니다.
void Enter();
// 상태에 머무르는 동안 매 프레임 호출됩니다. (Update 역할)
void Execute();
// 상태를 빠져나갈 때 한 번 호출됩니다.
void Exit();
}
2. 구체적인 상태 클래스 만들기(Idle, Move)
이제 IState 인터페이스를 상속받아 실제 상태들을 구현해 봅니다. 각 상태는 자신이 속한 플레이어 객체(Context)를 참조하여 제어합니다.
(대기상태)
using UnityEngine;
public class IdleState : IState
{
private PlayerController player;
// 생성자를 통해 플레이어 객체를 받아옵니다.
public IdleState(PlayerController player)
{
this.player = player;
}
public void Enter()
{
Debug.Log("Enter Idle State");
}
public void Execute()
{
// 방향키가 입력되면 Walk State로 전환합니다.
if (Input.GetAxisRaw("Horizontal") != 0 || Input.GetAxisRaw("Vertical") != 0)
player.ChangeState(new MoveState(player));
}
public void Exit()
{
Debug.Log("Exit Idle State");
}
}
(이동 상태)
using UnityEngine;
public class MoveState : IState
{
private PlayerController player;
public MoveState(PlayerController player)
{
this.player = player;
}
public void Enter()
{
Debug.Log("Enter Move State");
}
public void Execute()
{
float moveX = Input.GetAxisRaw("Horizontal");
float moveY = Input.GetAxisRaw("Vertical");
// 이동 로직(예시)
player.transform.Translate(new Vector3(moveX, moveY, 0).normalized * player.speed * Time.deltaTime);
if (moveX == 0 && moveY == 0)
{
player.ChangeState(new IdleState(player));
}
}
public void Exit()
{
Debug.Log("Exit Move State");
}
}
다양한 상태들을 개별적인 클래스로 구현하면 됩니다.
3. 상태 관리자(Context) 만들기
마지막으로 이 상태들을 담고 실행해 줄 MonoBehaviour 스크립트가 필요합니다. 유니티 프로젝트에 컴포넌트로 부착될 클래스입니다.
using UnityEngine;
public class PlayerController : MonoBehaviour
{
private IState currentState;
public float speed = 5f;
void Start()
{
// 게임이 시작되면 초기 상태를 Idle로 설정합니다.
ChangeState(new IdleState(this));
}
void Update()
{
// 매 프레임 현재 상태의 Execute()를 실행합니다.
if (currentState != null)
currentState.Execute();
}
// 상태를 변경하는 핵심 메서드입니다.
public void ChangeState(IState newState)
{
if (currentState != null)
currentState.Exit();
currentState = newState;
currentState.Enter();
}
}
코드를 보면 PlayerController의 Update 문 안에 조건문이 하나도 없습니다. 플레이어 스크립트는 그저 현재 상태에게 실행을 위임하고 있습니다.
처음 상태 패턴을 적용할 때는 클래스 파일이 많아져서 번거롭게 느껴질 수 있으나 장기적인 프로젝트나 기획 변경이 잦은 게임을 개발할 때, 상태 패턴은 개발 비용을 줄여줄 강력한 무기가 될 것입니다.
상태 패턴과 FSM의 차이
- 상태 패턴: 현재 상태 안에서 구체적으로 어떤 행동을 할 것인가(Behavior)?를 클래스로 깔끔하게 분리하여 캡슐화하는 데 집중합니다.
- FSM: 어떤 조건에서 다음 상태로 넘어갈 것인가(Transition)?라는 규칙과 흐름의 설계도에 집중합니다.
'Unity > 디자인 패턴' 카테고리의 다른 글
| [게임 디자인 패턴] 추상 팩토리 패턴(Abstract Factory Pattern) (0) | 2026.07.14 |
|---|---|
| [게임 디자인 패턴] 전략 패턴(Strategy Pattern) (0) | 2026.07.14 |
| [게임 디자인 패턴] 옵저버 패턴(Observer Pattern) (0) | 2026.07.14 |
| [게임 디자인 패턴]이벤트 버스(Event Bus) (0) | 2026.07.14 |
| [게임 디자인 패턴] Singleton (0) | 2024.04.08 |