Maszyna stanów
Część sekcji Architektura gier w Unity ścieżki Unity w Coddy. Lekcja 29 z 50.
Metoda SetState obiektu Beacon byłaby taka sama dla każdego obiektu ze stanami: wieżyczki, przeciwnika, drzwi. Ten kod może znajdować się we własnej klasie — maszynie stanów, która przechowuje bieżący stan i go zmienia. Każdy obiekt tworzy jedną maszynę i ją wywołuje, zamiast powtarzać kod:
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();
}
}Pierwsze wywołanie ChangeState nie ma stanu, z którego mogłoby wyjść: Current ma wartość null, a ?. pomija wywołanie Exit. W sekcji 1 było ostrzeżenie, że ?. nie wykrywa fałszywego null w Unity; dotyczy to zniszczonych obiektów Unity, a stany są zwykłymi obiektami C#, więc ?. jest tutaj bezpieczne. Właściwość Current ma private set, więc żaden skrypt nie może zmienić stanu bez przejścia przez ChangeState oraz jego Exit i Enter.
Kolejność wewnątrz ChangeState ma znaczenie zawsze, gdy dwa stany wpływają na ten sam element. Exit cofa zmiany wprowadzone przez stary stan, a następnie Enter przygotowuje nowy, więc ostatnie słowo należy do nowego stanu. Gdyby Enter stanu DarkState wyłączało lampę i uruchamiało się przed Exit stanu BlinkState, to Exit ponownie włączyłoby lampę w ciemnym stanie. StateMachine również jest zwykłą klasą: latarnia, wieżyczka i przeciwnik tworzą własne maszyny za pomocą new i wywołują ich Tick z poziomu Update.
Wyzwanie
ŚredniPrzytrzymaj Spację, aby skradać się. WalkState i SneakState są gotowe w PlayerStates.cs: ich Enter i Exit zapisują w logu, co się dzieje (Walk: enter, Sneak: exit...), a ich Tick wywołuje Move() gracza. Napisz maszynę, która nimi zarządza.
- W
StateMachine.csnapisz zwykłą klasęStateMachinez publiczną właściwościąCurrent, którą może ustawiać tylko maszyna, metodąChangeState(IState next), która wywołuje Exit poprzedniego stanu, a następnie Enter nowego stanu, oraz metodąTick(), która wywołuje Tick bieżącego stanu. - Gracz pyta o swój stan w każdej klatce, więc wywołanie
ChangeStateze stanem, który jest już bieżący, nic nie robi: nie wywołuje Exit ani Enter. - W
Player.csdodaj poleStateMachineo nazwiemachine. W Start utwórz maszynę i oba stany (każdy przyjmuje gracza) oraz rozpocznij chodzenie. W Update przełącz na skradanie, gdy Spacja jest wciśnięta, a w przeciwnym razie na chodzenie, a następnie wykonaj Tick maszyny.
Naciśnij Play, chodź, przytrzymaj Spację i dalej chodź, a następnie naciśnij Check.
Spróbuj swoich sił
// StateMachine: Current, ChangeState i Tick
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
1Komponenty, nie hierarchie
Małe komponentyPodstawowy skrypt przeciwnikaKomponenty abstrakcyjneWspółpracujące komponentyPodsumowanie: modułowa wieżyczka4Dane serializowane
Klasy serializowalneListy w InspectorzeWyliczenia w InspectorzePodsumowanie: tabela łupów10Projekt: Arena przetrwania
BohaterTypy wrogów2Interfejsy w Unity
IDamageableInterfejsy i TryGetComponentGetComponentsPodsumowanie: klawisz interakcji5ScriptableObjects
Zasoby danychStatystyki broniWspółdzielone ustawieniaFale jako danePowtórka: baza danych przedmiotów8Kod wielokrotnego użytku
Metody rozszerzająceGeneryczny singletonGeneryczne metody pomocniczePodsumowanie: FindNearest