State Pattern

감사콩·2025년 11월 18일

유니티

목록 보기
19/29
post-thumbnail

시작 전에

개인 프로젝트 준비를 위해 당분간 TIL 작성은 간결하게 진행하겠다.
대신 이번 프로젝트도 마찬가지로 제작일지를 동시에 작성 예정.

기본적으로 코드로 복습 예정인데
예시 코드는 기존과 같이 비공개로 업로드 예정.

서론


상태 패턴을 이해하고 활용해보자.
코드 위주의 내용이므로 간단히 정의만 정리하고
복습용 코드는 비공개로 게시.


TIL 요약


  • 상태 패턴은 게임 구현에서 자주 사용되는 디자인 패턴.

State Pattern(상태 패턴)


상태 패턴이란?
객체의 내부 상태(State)가 바뀜에 따라 객체의 행위(Behavior)를 변경할 수 있게 해주는 디자인 패턴

복잡한 조건문을 사용하여 상태별 행위를 구현하는 대신
각 상태를 독립된 클래스로 분리하여 관리함으로써
코드의 유지보수성확장성을 높일 수 있다.


원리


복잡한 상태 전환 로직을 캡슐화하고 분리하는 걸 중점으로 둠.

기존의 상태전환 로직의 예시로는

if(currentState == StateA)
{
	Do A
}

위와 같이 하나의 객체 내부에 수많은 조건문을 사용하여
상태를 체크하고, 그에 맞는 로직을 실행하는 방식이였음.

이 상태별 행동(Behavior) 을 상태를 나타낼 객체에게 위임하는 방식.


방식


주로 3가지 구성요소를 지님.

  1. Context: 상태별 행동을 수행할 객체
  2. State: 상태 인터페이스/추상 클래스 를 활용해 모든 상태가 구현해야 할 공통 행동 정의.
  3. ConcreteState (구체적 상태): State 인터페이스를 구현, 특정 상태에서의 행위를 정의.
    필요 시, 다른 상태로의 전환도 담당 가능.

예시


게임에서의 행동 유닛의 상태에 적용할 수 있다.

Player의 상태?
Idle, Walk, Run, Jump 등등
이 예시를 간단히 코드로 구현해보겠다.

구현 순서


인터페이스 방식 채용

1. State 인터페이스 (IPlayerState)

인터페이스로 모든 상태에서 필요한 메서드를 강제

// 모든 상태가 구현해야 할 공통 인터페이스
public interface IPlayerState
{
    void EnterState(Player player);
    void HandleInput(Player player);
    void Update(Player player);
}

2. 각 상태별 클래스

ConcreteState(IdleState, WalkState 등)
해당 상태만의 로직을 구현.

public class IdleState : IPlayerState
{
    public void Update(Player player))
    {
        if (벡터값이 있으면?))
        {
            //상태 전환
            player.ChangeState(new WalkState());
        }
    }
    다른 메서드 구현
}

3. Context 클래스 (Player)

현재 상태 객체의 참조 유지, 모든 상태별 요청을 이 객체에 위임.

public class Player
{
    //1. 현재 상태 객체 참조
    private IPlayerState _currentState;

    public Player()
    {
        // 초기 상태 설정
        _currentState = new IdleState();
        _currentState.EnterState(this);
    }

    // 2. 상태 변경용 메서드
    public void ChangeState(IPlayerState newState)
    {
        // 상태 변경
        _currentState = newState;
        // 새로운 상태의 시작 로직 호출
        _currentState.EnterState(this);
    }

    // 3. Context의 동작을 현재 상태 객체에 위임
    public void Update()
    {
        _currentState.Update(this);
    }
}

이러면 기본적인 Player 움직임 상태패턴 구현 완료.


장점


  • 상태 분리:
    상태별 행위 로직이 하나의 Context 클래스에 집중되지 않고
    각 ConcreteState 클래스로 분리

  • 유지보수 용이
    새로운 상태를 추가할 때, 기존 Context 클래스의 코드를 수정(조건문 추가)할 필요 없이
    새로운 상태 클래스만 추가

  • 다형성 활용
    객체 지향의 다형성(Polymorphism)을 활용하여 상태별 행위를 실행

이런 이점을 갖고 있기에 필요 시에 활용하면 좋다.



마무리


오늘은 상태 패턴이라는 디자인 패턴을 알아보았다.
내일은 이와 흡사한 Behavior Tree(BT) 구조를 알아보고
Unity 6부터 제공하는 BT 그래프 기능 (Behavior Graph) 또한 알아보겠다.

profile
안녕하시와요

0개의 댓글