Menu
CoddyTech

Stany jako klasy

Część sekcji Architektura gier w Unity ścieżki Unity w Coddy. Lekcja 28 z 50.

Sekcja 3 pokazuje przełącznik oparty na wyliczeniu, który skupia obsługę każdego stanu w jednej metodzie Update. Takie rozwiązanie przestaje się skalować, gdy stany mają własne dane: timer używany tylko przez jeden stan staje się polem MonoBehaviour, obok pól wszystkich pozostałych stanów, a każdy przypadek musi pamiętać o resetowaniu używanych danych. Wzorzec stanu z C# przypisuje każdemu stanowi własną klasę, a każda klasa implementuje jeden interfejs. Ta lampa drogowa miga lub świeci światłem ciągłym, a klawisz Space przełącza między tymi dwoma stanami:

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();
    }
}

Stany są zwykłymi klasami C#, a nie MonoBehaviour. Tworzysz je za pomocą new i przekazujesz im potrzebne dane przez konstruktor — tutaj Renderer lampy — ponieważ nie są komponentami i nie mogą wywoływać GetComponent ani wyświetlać pól w Inspectorze. Unity również nie wywołuje ich metod: Beacon jest MonoBehaviour, więc jego Update wywołuje current.Tick() w każdej klatce.

timer należy wyłącznie do BlinkState, a jego Enter ustawia go na 0 za każdym razem, gdy lampa zaczyna migać. Exit sprząta po zakończeniu stanu: Space można nacisnąć, gdy lampa jest wyłączona, a Exit włącza ją z powrotem, więc SteadyState nigdy nie rozpoczyna działania przy zgaszonej lampie. SetState uruchamia Exit poprzedniego stanu, a następnie Enter nowego stanu. Trzeci stan, taki jak powolne pulsowanie, wymaga tylko jednej dodatkowej klasy, a Update w Beacon pozostaje bez zmian.

challenge icon

Wyzwanie

Średni

Wieżyczka strażnicza pilnuje podwórka. Strzałkami steruj obiektem Player (gotowy). Nadaj wieżyczce dwa stany zapisane jako klasy:

  • W pliku IState.cs zadeklaruj public interface IState z metodami void Enter(), void Tick() i void Exit().
  • W pliku TurretStates.cs napisz dwie zwykłe klasy, które implementują ten interfejs. ScanState pobiera głowicę wieżyczki w konstruktorze. Zamiata głowicą z boku na bok: lokalny kąt y głowicy zmienia się z szybkością 90 stopni na sekundę, między -45 a 45, zaczynając od 0 i za każdym razem, gdy rozpoczyna się skanowanie, obracając się w górę. Jego metoda Enter koloruje również głowicę na Color.green.
  • AlertState pobiera głowicę i gracza. Jego metoda Enter koloruje głowicę na Color.red i zapisuje w logu Intruder!; metoda Tick obraca głowicę tak, aby była skierowana w stronę gracza wyłącznie wokół osi y, bez przechylenia; metoda Exit zapisuje w logu All clear.
  • W pliku Turret.cs utwórz oba stany w metodzie Start i rozpocznij skanowanie. W każdej klatce przełączaj się na stan alarmu, gdy gracz znajduje się bliżej wieżyczki niż range (4), a gdy nie, wracaj do skanowania, a następnie uruchamiaj metodę Tick bieżącego stanu. Przy zmianie uruchom metodę Exit starego stanu, a następnie metodę Enter nowego stanu.

Naciśnij Play, podejdź do wieżyczki, a potem oddal się od niej i naciśnij Check.

Spróbuj swoich sił

using UnityEngine;

// ScanState i AlertState
quiz iconSprawdź się

Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.

Wszystkie lekcje w sekcji Architektura gier w Unity