Menu
CoddyTech

클래스로 구현하는 상태

Coddy Unity 여정의 Unity 게임 아키텍처 섹션에 포함된 레슨. 64개 중 35번째.

섹션 3의 enum을 사용하는 switch문은 모든 상태의 작업을 하나의 Update에 모아 둡니다. 하지만 상태마다 고유한 데이터가 생기면 이 방식은 확장에 한계가 있습니다. 한 상태만 사용하는 타이머도 MonoBehaviour의 필드가 되어 다른 모든 상태의 필드 옆에 놓이고, 각 case는 자신이 사용하는 값을 초기화하는 일을 기억해야 합니다. C#의 상태 패턴에서는 각 상태가 자체 클래스를 가지며, 모든 클래스가 하나의 인터페이스를 구현합니다. 이 도로 표지등은 깜박이거나 계속 켜져 있고, Space 키를 누르면 두 상태 사이를 전환합니다:

public interface IState
{
    void Enter();
    void Tick();
    void Exit();
}

public class BlinkState : IState
{
    private Renderer lamp;
    private float timer;

    public BlinkState(Renderer lamp)
    {
        this.lamp = lamp;
    }

    public void Enter() { timer = 0f; }

    public void Tick()
    {
        timer += Time.deltaTime;
        if (timer >= 0.5f)
        {
            timer = 0f;
            lamp.enabled = !lamp.enabled;
        }
    }

    public void Exit() { lamp.enabled = true; }
}

public class SteadyState : IState
{
    public void Enter() { }
    public void Tick() { }
    public void Exit() { }
}

public class Beacon : MonoBehaviour
{
    public Renderer lamp;
    private IState blink;
    private IState steady;
    private IState current;

    void Start()
    {
        blink = new BlinkState(lamp);
        steady = new SteadyState();
        SetState(steady);
    }

    void Update()
    {
        if (Keyboard.current.spaceKey.wasPressedThisFrame) SetState(current == steady ? blink : steady);
        current.Tick();
    }

    void SetState(IState next)
    {
        if (current != null) current.Exit();
        current = next;
        current.Enter();
    }
}

상태는 MonoBehaviour가 아닌 일반 C# 클래스입니다. new로 인스턴스를 만들고 생성자를 통해 필요한 것을 전달합니다. 여기서는 램프의 Renderer를 전달하는데, 이 클래스들은 컴포넌트가 아니므로 GetComponent를 호출하거나 Inspector에 필드를 표시할 수 없기 때문입니다. Unity는 이 클래스들의 메서드도 호출하지 않습니다. Beacon이 MonoBehaviour이므로 Beacon의 Update가 매 프레임 current.Tick()을 호출합니다.

timer는 BlinkState에만 속하며, Enter는 표지등이 깜박이기 시작할 때마다 timer를 0으로 설정합니다. Exit는 상태가 끝날 때 정리 작업을 합니다. 램프가 꺼져 있을 때 Space 키를 누를 수도 있는데, Exit가 램프를 다시 켜므로 SteadyState는 램프가 꺼진 채로 시작하지 않습니다. SetState는 기존 상태의 Exit를 실행한 다음 새 상태의 Enter를 실행합니다. 느린 점멸과 같은 세 번째 상태를 추가하려면 클래스를 하나 더 만들면 되며, Beacon의 Update는 바뀌지 않습니다.

challenge icon

챌린지

중급

터렛의 스캔 상태를 작성하세요.

  1. IState.cs에서 public interface IState를 선언하고 void Enter();, void Tick();, void Exit();를 작성하세요.
  2. TurretStates.cs에서 헤드를 전달받는 ScanState : IState를 작성하세요. 진입 시 각도를 0으로 설정하고 헤드의 색을 Color.green으로 설정하세요. Tick에서는 헤드의 로컬 y 각도를 초당 90도씩 -45에서 45 사이로 회전시키세요.
  3. Turret에서는 Start에서 상태에 진입하고 Update에서 상태를 진행시키세요.

‘플레이’를 누르세요. 초록색 헤드가 회전합니다. 그런 다음 ‘확인’을 누르세요.

직접 해보기

using UnityEngine;

// ScanState

Unity 게임 아키텍처의 모든 레슨

직접 연습해 보세요: Unity 플레이그라운드