전환
Coddy Unity 여정의 Unity 게임 아키텍처 섹션에 포함된 레슨. 50개 중 30번째.
상태가 언제 바뀔지는 누가 결정할까요? 소유자가 결정하게 하면 switch에서처럼 모든 규칙이 하나의 Update 안으로 다시 모입니다. 일반적으로는 각 상태가 자기만의 탈출 방법을 알고 있다고 봅니다. Tick에서 조건을 확인하고 기계에 다음 상태를 요청하는 방식입니다. 이 폭탄은 플레이어가 가까이 올 때까지 기다렸다가 도화선에 불을 붙이고, 플레이어가 달아나면 대기 상태로 돌아갑니다.
public class Bomb : MonoBehaviour
{
public Transform player;
public StateMachine machine = new StateMachine();
public IState idle;
public IState fuse;
void Start()
{
idle = new IdleState(this);
fuse = new FuseState(this);
machine.ChangeState(idle);
}
void Update() { machine.Tick(); }
public bool PlayerNear()
{
return Vector3.Distance(transform.position, player.position) < 3f;
}
}
public class IdleState : IState
{
private Bomb bomb;
public IdleState(Bomb bomb) { this.bomb = bomb; }
public void Enter() { }
public void Exit() { }
public void Tick()
{
if (bomb.PlayerNear()) bomb.machine.ChangeState(bomb.fuse);
}
}
public class FuseState : IState
{
private Bomb bomb;
private float timer;
public FuseState(Bomb bomb) { this.bomb = bomb; }
public void Enter() { timer = 2f; }
public void Exit() { }
public void Tick()
{
if (!bomb.PlayerNear())
{
bomb.machine.ChangeState(bomb.idle);
return;
}
timer -= Time.deltaTime;
if (timer <= 0f)
{
Debug.Log("Boom!");
Object.Destroy(bomb.gameObject);
}
}
}각 상태는 생성자에서 폭탄을 전달받고, 이를 통해 기계와 플레이어 확인 기능, 그리고 다른 상태에 접근합니다. 폭탄은 Start에서 각 상태를 한 번씩 만들기 때문에 상태가 new를 사용해 다른 상태를 만들지는 않습니다. 서로의 생성자에서 상대 상태를 만드는 두 상태는 스택이 넘칠 때까지 반복됩니다. 폭탄의 Update는 기계를 틱하는 일만 하고, 각 규칙은 해당 규칙이 속한 상태 안에 있습니다. 2초 도화선은 오직 FuseState만 담당합니다.
ChangeState는 FuseState의 Exit과 IdleState의 Enter를 즉시 실행하지만, 호출 이후에도 FuseState의 Tick 나머지 부분은 계속 실행됩니다. return으로 실행을 멈추지 않으면 이미 끝난 상태의 도화선이 한 프레임 더 타게 됩니다. Destroy는 Object.Destroy라고 작성합니다. MonoBehaviour는 Unity의 Object 클래스에서 이를 상속하지만, 일반 클래스에서는 클래스 이름을 명시해야 합니다.
챌린지
중급파리지옥은 다가오는 사람을 덮칩니다. Flytrap.cs는 준비되어 있습니다. 머신과 세 가지 상태(공개 필드 open, snap, chew)를 만들고, Open 상태로 시작해 매 프레임마다 머신을 틱하며, PlayerInReach()는 플레이어가 지면을 따라 2보다 가까이 있는지 알려줍니다. FlytrapStates.cs에는 각 Enter가 작성되어 있습니다(색상, 타이머, Chomp! 로그). 각 상태의 Tick에서 상태 전환을 작성하세요.
- Open: 플레이어가 범위 안에 들어오면 덫이 덮칩니다.
- Snap은 0.5초 동안 지속됩니다. 그 후 플레이어가 여전히 범위 안에 있으면 덫이 씹고, 플레이어가 도망갔으면 다시 열립니다.
- Chew는 주변에 누가 있든 3초 동안 지속된 후 덫이 다시 열립니다.
화살표 키로 Player를 이동합니다. Play를 누르고 덫 안으로 걸어 들어간 다음, 피할 수 있는지 시도해 보고 Check를 누르세요.
직접 해보기
using UnityEngine;
public class OpenState : IState
{
private Flytrap trap;
public OpenState(Flytrap trap)
{
this.trap = trap;
}
public void Enter()
{
trap.Paint(new Color(0.3f, 0.8f, 0.2f));
}
public void Tick()
{
// 플레이어가 사정거리 안에 들어오면 닫기
}
public void Exit()
{
}
}
public class SnapState : IState
{
private Flytrap trap;
private float timer;
public SnapState(Flytrap trap)
{
this.trap = trap;
}
public void Enter()
{
timer = 0f;
trap.Paint(new Color(1f, 0.55f, 0.1f));
}
public void Tick()
{
// 0.5초 후: 플레이어가 여전히 사정거리 안에 있으면 씹고, 그렇지 않으면 다시 열기
}
public void Exit()
{
}
}
public class ChewState : IState
{
private Flytrap trap;
private float timer;
public ChewState(Flytrap trap)
{
this.trap = trap;
}
public void Enter()
{
timer = 3f;
trap.Paint(new Color(0.5f, 0.05f, 0.1f));
Debug.Log("Chomp!");
}
public void Tick()
{
// 3초 후: 다시 열기
}
public void Exit()
{
}
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.