Menu
CoddyTech

적의 두뇌

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

적의 두뇌는 행동마다 하나의 상태가 있는 상태 머신입니다. 이 기본 구조는 정해진 지점 사이를 오가고, 6 유닛 이내로 다가오는 플레이어를 쫓으며, 가까이 있으면 초당 한 번 검을 휘두릅니다. 각 상태는 자체적으로 다음 상태로 전환할 조건을 결정하고, 스켈레톤은 상태들이 함께 사용하는 도우미를 유지합니다:

public class Skeleton : MonoBehaviour
{
    public Transform player;
    public Transform[] posts;
    public float speed = 2f;
    public StateMachine machine = new StateMachine();
    public IState patrol, chase, attack;

    void Start()
    {
        patrol = new PatrolState(this);
        chase = new ChaseState(this);
        attack = new AttackState(this);
        machine.ChangeState(patrol);
    }

    void Update() { machine.Tick(); }

    public float PlayerDistance() { return Vector3.Distance(transform.position, player.position); }

    public void WalkTo(Vector3 target)
    {
        target.y = transform.position.y;
        transform.position = Vector3.MoveTowards(transform.position, target, speed * Time.deltaTime);
    }
}

public class PatrolState : IState
{
    private Skeleton skel;
    private int next;
    public PatrolState(Skeleton skel) { this.skel = skel; }
    public void Enter() { }
    public void Exit() { }

    public void Tick()
    {
        if (skel.PlayerDistance() < 6f) { skel.machine.ChangeState(skel.chase); return; }
        Vector3 post = skel.posts[next].position;
        post.y = skel.transform.position.y;
        skel.WalkTo(post);
        if (skel.transform.position == post) next = (next + 1) % skel.posts.Length;
    }
}

public class ChaseState : IState
{
    private Skeleton skel;
    public ChaseState(Skeleton skel) { this.skel = skel; }
    public void Enter() { }
    public void Exit() { }

    public void Tick()
    {
        float d = skel.PlayerDistance();
        if (d > 6f) { skel.machine.ChangeState(skel.patrol); return; }
        if (d < 1.5f) { skel.machine.ChangeState(skel.attack); return; }
        skel.WalkTo(skel.player.position);
    }
}

public class AttackState : IState
{
    private Skeleton skel;
    private float cooldown;
    public AttackState(Skeleton skel) { this.skel = skel; }
    public void Enter() { cooldown = 0f; }
    public void Exit() { }

    public void Tick()
    {
        if (skel.PlayerDistance() > 1.5f) { skel.machine.ChangeState(skel.chase); return; }
        cooldown -= Time.deltaTime;
        if (cooldown <= 0f) { Debug.Log("Swing!"); cooldown = 1f; }
    }
}

상태는 한 번만 만들어지고 스켈레톤이 살아 있는 동안 유지되므로, 상태의 필드 값도 상태를 다시 방문할 때까지 유지됩니다. 추격을 마친 뒤에도 PatrolState의 next 값은 그대로라서 스켈레톤은 향하던 지점까지 계속 걸어갑니다. Enter는 다시 초기화해야 하는 값만 초기화합니다. AttackState의 Enter는 cooldown을 0으로 설정하므로, 스켈레톤이 플레이어에게 도달하면 곧바로 첫 공격을 합니다.

모든 이동은 WalkTo를 거칩니다. 여기서는 트랜스폼에 MoveTowards를 사용하며, 이 방법은 벽을 통과해 이동합니다. 대신 Rigidbody로 스켈레톤을 움직이려면 WalkTo에서 본체의 속도를 설정하고, 스켈레톤은 물리 단계인 FixedUpdate에서 상태 머신을 틱해야 합니다. 이때 Time.deltaTime은 물리 단계의 시간 간격입니다. 세 상태는 바뀌지 않습니다. 상태는 어디로 갈지 말하고, 소유자는 어떻게 움직일지 결정합니다.

challenge icon

챌린지

중급

KnightStates.cs에서 기사에게 PatrolState와 ChaseState를 각각 만들어 줘.

  1. 순찰: waypoints[next]로 걸어가. 0.3 이내에 도달하면 next를 다음 항목으로 옮기고, 순환하도록 해서 방문 순서를 유지해. sightRange보다 가까우면 추격해.
  2. 추격: 플레이어에게 걸어가. loseRange보다 멀어지면 순찰해.
  3. Knight에서 Awake에 상태 머신과 상태를 만들고, Start에서 순찰 상태로 설정하고, FixedUpdate에서 틱을 처리해.

‘플레이’를 누른 다음, 가까이 다가가서 달려. 그런 다음 ‘확인’을 눌러.

직접 해보기

using UnityEngine;

// PatrolState와 ChaseState

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

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