클래스로 구현하는 상태
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는 바뀌지 않습니다.
챌린지
중급터렛의 스캔 상태를 작성하세요.
IState.cs에서public interface IState를 선언하고void Enter();,void Tick();,void Exit();를 작성하세요.TurretStates.cs에서 헤드를 전달받는ScanState : IState를 작성하세요. 진입 시 각도를 0으로 설정하고 헤드의 색을Color.green으로 설정하세요. Tick에서는 헤드의 로컬 y 각도를 초당90도씩-45에서45사이로 회전시키세요.Turret에서는 Start에서 상태에 진입하고 Update에서 상태를 진행시키세요.
‘플레이’를 누르세요. 초록색 헤드가 회전합니다. 그런 다음 ‘확인’을 누르세요.
직접 해보기
using UnityEngine;
// ScanState
Unity 게임 아키텍처의 모든 레슨
직접 연습해 보세요: Unity 플레이그라운드