Menu
CoddyTech

Zum Zustand wechseln

Teil des Abschnitts Echte Spiele entwickeln der Unity-Journey von Coddy. Lektion 15 von 60.

Jeder Zustand eines Spiels erledigt in jedem Frame andere Aufgaben. Ein switch für das Zustandsfeld ordnet diese Aufgaben je Zustand einem case zu, und in jedem Frame wird genau ein case ausgeführt. Der Zustandswechsel erfolgt über eine einzige Methode, sodass der Bildschirm immer dem Zustand entspricht. Dieser Bosskampf hat eine Einführung, den Kampf und einen Siegbildschirm:

public enum Phase { Intro, Fight, Won }

public class BossFight : MonoBehaviour
{
    public GameObject introPanel;
    public GameObject fightPanel;
    public GameObject winPanel;
    public int bossHp = 10;
    private Phase phase;
    private float timer = 3f;

    void Start()
    {
        Enter(Phase.Intro);
    }

    void Update()
    {
        switch (phase)
        {
            case Phase.Intro:
                timer -= Time.deltaTime;
                if (timer <= 0f) Enter(Phase.Fight);
                break;
            case Phase.Fight:
                if (bossHp <= 0) Enter(Phase.Won);
                break;
            case Phase.Won:
                break;
        }
    }

    void Enter(Phase next)
    {
        phase = next;
        introPanel.SetActive(next == Phase.Intro);
        fightPanel.SetActive(next == Phase.Fight);
        winPanel.SetActive(next == Phase.Won);
    }
}

Jeder case endet mit break, weil C# die Kompilierung verweigert, wenn ein case einfach mit dem nächsten fortgesetzt wird. Wenn der Timer der Einführung abläuft, ändert Enter(Phase.Fight) die Phase, aber der Fight-case wird erst im nächsten Frame ausgeführt, da dieser Frame seinen case bereits ausgewählt hat. Bei mehreren separaten if-Blöcken hintereinander könnte ein Frame den Kampf starten und im selben Frame den Kampfcode ausführen.

Enter ist der einzige Ort, an dem phase geändert wird. next == Phase.Fight ist nur für das Kampfpanel true, sodass ein Aufruf dieses Panel anzeigt und die beiden anderen ausblendet. Aufgaben, die zum Betreten eines Zustands gehören, etwa das Zurücksetzen eines Timers, gehören ebenfalls in Enter und werden einmal statt in jedem Frame ausgeführt.

challenge icon

Aufgabe

Einfach

Mach das 5-Sekunden-Tipp-Rennen.

  1. Zeige in SetState nur das Panel des neuen Zustands an. Beim Wechsel zu Playing werden taps = 0, timeLeft = roundTime und Taps: 0 gesetzt; beim Wechsel zu GameOver wird Taps: 3 in resultText angezeigt.
  2. Verwende in Update() switch (state): Mit der Leertaste wechselst du von Ready zu Playing und von GameOver zu Ready; während Playing zählt jeder Druck auf die Leertaste in taps und tapsText, bis die Zeit abgelaufen ist.

Drücke „Spielen“ und tritt zweimal gegen die Zeit an. Drücke dann „Prüfen“.

Probier es selbst

using UnityEngine;
using TMPro;

public enum GameState { Ready, Playing, GameOver }

public class GameManager : MonoBehaviour
{
    public GameObject readyPanel;
    public GameObject playPanel;
    public GameObject gameOverPanel;
    public TMP_Text tapsText;
    public TMP_Text resultText;
    public float roundTime = 5f;
    public GameState state;
    private int taps;
    private float timeLeft;

    void Start()
    {
        SetState(GameState.Ready);
    }

    void Update()
    {
        // je nach state verzweigen:
        // Ready: Space startet eine Runde
        // Playing: Space zählt einen Tipp; wenn die Zeit abgelaufen ist, ist das Spiel vorbei
        // GameOver: Space wechselt zurück zu Ready
    }

    void SetState(GameState next)
    {
        state = next;
        // nur das Panel des neuen Zustands anzeigen
        // eine neue Runde beginnt mit 0 Tipps und roundTime Sekunden; am Ende zeigt resultText die Anzahl der Tipps an
    }
}

Alle Lektionen in Echte Spiele entwickeln

Übe selbstständig: Unity-Playground