Stany jako klasy
Część sekcji Architektura gier w Unity ścieżki Unity w Coddy. Lekcja 35 z 64.
Przełącznik z sekcji 3, oparty na enumie, skupia obsługę wszystkich stanów w jednej metodzie Update. To 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 zresetowaniu używanych wartości. Wzorzec stanu z C# przypisuje każdemu stanowi osobną klasę, a każda klasa implementuje jeden interfejs. Ta latarnia drogowa miga albo ś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 to zwykłe klasy C#, a nie MonoBehaviours. Tworzysz je za pomocą new i przekazujesz im potrzebne elementy 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 latarnia zaczyna migać. Exit porządkuje stan po jego zakończeniu: klawisz Space może zostać naciśnięty, gdy lampa jest wyłączona, a Exit ponownie ją włącza, dzięki czemu SteadyState nigdy nie zaczyna działania przy zgaszonej lampie. SetState wywołuje Exit poprzedniego stanu, a następnie Enter nowego. Trzeci stan, na przykład powolne pulsowanie, to kolejna klasa, a Update w Beacon pozostaje bez zmian.
Wyzwanie
ŚredniNapisz stan skanowania wieżyczki.
- W pliku
IState.cszadeklarujpublic interface IStatez metodamivoid Enter();,void Tick();ivoid Exit();. - W pliku
TurretStates.csnapiszScanState : IState, przekazując głowicę. Enter: kąt 0, głowicaColor.green. Tick: obracaj głowicę wokół lokalnej osi y między-45a45, z prędkością90stopni na sekundę. Turret: rozpocznij działanie jednego stanu w Start, wywołuj jego Tick w Update.
Naciśnij „Graj”: zielona głowica będzie się obracać. Następnie naciśnij „Sprawdź”.
Spróbuj swoich sił
using UnityEngine;
// ScanState
Wszystkie lekcje w sekcji Architektura gier w Unity
1Komponenty, nie hierarchie
Małe komponentyBazowy skrypt przeciwnikaKomponenty abstrakcyjneWspółpracujące komponentyPowtórka: modułowa wieżyczkaPowtórka: podwójne działo4Dane serializowane
Klasy serializowalneListy w InspectorzeEnumy w InspectorzePodsumowanie: tabela łupówPodsumowanie: losowanie łupów7Maszyny stanów
Stany jako klasyStan alarmowyMaszyna stanówPrzejściaMózgi przeciwnikówAtaki rycerzaPodsumowanie: stany drzwi2Interfejsy w Unity
IDamageableInterfejsy i TryGetComponentGetComponentsPowtórka: klawisz interakcjiPowtórka: najbliższy w zasięgu5ScriptableObjects
Zasoby danychStatystyki broniWspółdzielone ustawieniaOcal wiatrFale jako danePowtórka: Baza przedmiotówPowtórka: Kupowanie w sklepie8Kod wielokrotnego użytku
Metody rozszerzająceGeneryczny singletonGeneryczne metody pomocniczePodsumowanie: FindNearestPoćwicz samodzielnie: Edytor online Unity