Menu
CoddyTech

Máy trạng thái

Thuộc phần Kiến trúc trò chơi trong Unity trong hành trình Unity của Coddy. Bài học 37 trên 64.

Phương thức SetState của Beacon sẽ giống nhau trong mọi đối tượng có các trạng thái: tháp pháo, kẻ địch, cánh cửa. Đoạn code đó có thể nằm trong một lớp riêng, máy trạng thái, giữ trạng thái hiện tại và thay đổi trạng thái đó. Mỗi đối tượng tạo một máy trạng thái và gọi máy đó, thay vì lặp lại đoạn code:

public class StateMachine
{
    public IState Current { get; private set; }

    public void ChangeState(IState next)
    {
        Current?.Exit();
        Current = next;
        Current.Enter();
    }

    public void Tick()
    {
        Current?.Tick();
    }
}

public class Beacon : MonoBehaviour
{
    public Renderer lamp;
    private StateMachine machine = new StateMachine();
    private IState blink;
    private IState steady;

    void Start()
    {
        blink = new BlinkState(lamp);
        steady = new SteadyState();
        machine.ChangeState(steady);
    }

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

Lần gọi ChangeState đầu tiên không có trạng thái nào để thoát: Current là null, và ?. bỏ qua lời gọi Exit. Phần 1 đã lưu ý rằng ?. không phát hiện được giá trị null giả của Unity; điều đó áp dụng cho các đối tượng Unity đã bị hủy, còn các trạng thái là đối tượng C# thông thường, nên ?. an toàn ở đây. Current có private set, nên không script nào có thể đổi trạng thái nếu không thông qua ChangeState cùng Exit và Enter.

Thứ tự bên trong ChangeState rất quan trọng mỗi khi hai trạng thái tác động lên cùng một thứ. Exit hoàn tác những gì trạng thái cũ đã thay đổi, sau đó Enter thiết lập trạng thái mới, nên trạng thái mới có quyền quyết định cuối cùng. Nếu Enter của DarkState tắt đèn và chạy trước Exit của BlinkState, thì Exit đó sẽ bật đèn trở lại trong trạng thái tối. StateMachine cũng là một lớp thông thường: đèn hiệu, tháp pháo và kẻ địch mỗi đối tượng tạo máy trạng thái riêng bằng new và gọi Tick từ Update.

challenge icon

Thử thách

Trung bình

Chạy các trạng thái sẵn sàng của người chơi bằng một máy trạng thái.

  1. Trong StateMachine.cs, viết public class StateMachine với public IState Current { get; private set; } và một phương thức Tick() để cập nhật trạng thái.
  2. ChangeState(IState next) bỏ qua trạng thái hiện tại; nếu không, gọi Exit, gán Current, rồi gọi Enter.
  3. Player: Start tạo machine, walk, sneak và chuyển sang trạng thái đi bộ; Update chuyển sang trạng thái rón rén khi bạn giữ Space, nếu không thì chuyển sang trạng thái đi bộ, rồi cập nhật trạng thái.

Nhấn Chơi và giữ Space: Sneak: enter. Sau đó nhấn Kiểm tra.

Tự làm thử

// StateMachine: Current, ChangeState và Tick

Tất cả bài học trong Kiến trúc trò chơi trong Unity

Tự luyện tập: Playground Unity