Metlivi Blog

So trennen Sie Idle- und interaktive Zustände in einem Game-Loop für virtuelle Haustiere

Trennen Sie bei einem virtuellen Haustierspiel autonomes Verhalten und Spieleraktionen in separate Aktualisierungspfade und lassen Sie beide denselben Haustierzustand über explizite Übergänge modifizieren. Das Idle-Verhalten sollte durch die verstrichene Zeit voranschreiten; interaktives Verhalten sollte auf Eingabe-Events oder den aktuellen Eingabezustand reagieren. Dies erleichtert das Pausieren und Testen und verhindert, dass eine Haustieranimation oder ein Bedürfnis-Timer mit einem Spielerbefehl in Konflikt gerät.

15. Oktober 20266 Min. LesezeitVon Metlivi Editorial Team
Abschnitt 1

Definieren Sie, was „Idle“ und „interaktiv“ bedeuten

Betrachten Sie diese als Verhaltensmodi, nicht zwingend als verschiedene Szenen oder separate Loops. Im Idle-Zustand führt das Haustier seine Routine aus: Es wählt eine kleine Umgebungsaktion, lässt einen Timer weiterlaufen oder spielt eine unwesentliche Animation ab. Im interaktiven Zustand verarbeitet das Spiel eine bewusste Aktion wie ein Antippen, Ziehen oder einen ausgewählten Befehl. Das Haustier kann auch während einer Interaktion animiert werden; der Unterschied besteht darin, welches System Entscheidungen treffen und den Spielzustand ändern darf.

Beginnen Sie mit einer kurzen Liste von Aktionen, die der Spieler ausführen kann, und den autonomen Verhaltensweisen, die das Haustier ausführen kann. Markieren Sie, welche Zustandsvariablen die jeweiligen Aktionen ändern dürfen. Beispielsweise betrifft ein gelegentliches Blinzeln möglicherweise nur die Darstellung, während eine ausgewählte Spielaktion die aktuelle Aktivität des Haustiers ändern und einen Timer starten kann. Diese einfache Zuordnung von Zuständigkeiten deckt Konflikte auf, bevor die Codebasis wächst.

Abschnitt 2

Halten Sie den äußeren Loop unabhängig vom Verhalten des Haustiers

Der Frame-Callback der Engine sollte die Abläufe koordinieren, anstatt alle Haustierregeln zu enthalten. Eine bewährte Sequenz ist: Eingaben erfassen, gültige Befehle anwenden, Simulation vorantreiben und anschließend den neuesten Zustand rendern. Trennen Sie die Eingabeerfassung von der Simulation, damit ein Antippen nicht versehentlich als Timer-Tick interpretiert wird, und halten Sie das Rendering frei von Änderungen an der Gameplay-Logik. Game Programming Patterns beschreibt diese Trennung als das Verarbeiten von Eingaben, Aktualisieren des Spiels und Rendern in einer sich wiederholenden Schleife; Aktualisierungen mit festen Schritten sind nützlich, wenn die Simulation ein stabiles Intervall benötigt. Game Loop, Game Programming Patterns

Bei einem Webspiel plant requestAnimationFrame Arbeiten vor dem Repaint ein und liefert einen Zeitstempel, mit dem Sie die verstrichene Zeit messen können. Browser pausieren diese Callbacks in der Regel in ausgeblendeten Tabs. Gehen Sie daher nicht davon aus, dass sie als verlässliche Echtzeituhr weiterlaufen, während das Spiel im Hintergrund liegt. Window.requestAnimationFrame(), MDN

Abschnitt 3

Leiten Sie Spielereingaben über Befehle weiter

Wandeln Sie Roheingaben in einen kurzen Befehl wie start_play, stop_play oder pet_tap um. Ein Command-Handler prüft, ob die Aktion für den aktuellen Modus gültig ist, aktualisiert das gemeinsame Modell einmalig und gibt die daraus resultierenden Hinweise für die Darstellung aus. Dadurch wird vermieden, dass Aktionslogik gleichzeitig in Button-Callbacks, Animations-Callbacks und der Idle-Routine liegt.

Wenn ein Spieler beispielsweise tippt, während das Haustier bereits spielt, definieren Sie das Ergebnis ganz bewusst: Ignorieren Sie das Tippen, wählen Sie eine andere Aktivität aus oder beenden Sie die Aktivität. Vermeiden Sie es, dass sowohl die Idle-Auswahl als auch der Tap-Handler während desselben Updates eine neue Aktivität zuweisen können. Behandeln Sie in Engines mit Event-Propagation Gameplay-Eingaben auf der passenden Ebene und berücksichtigen Sie die Verarbeitung durch die Benutzeroberfläche; die Godot-Dokumentation zu Node weist darauf hin, dass unbehandelte Eingaben meist besser für das Gameplay geeignet sind, wenn GUI-Bedienelemente Vorrang haben müssen. Node class, Godot documentation

Abschnitt 4

Lassen Sie die Idle-Zeit mit einer eindeutigen Uhr voranschreiten

Akkumulieren Sie bei Verhalten, das während einer sichtbaren Sitzung kontinuierlich ablaufen soll, die verstrichene Simulationszeit und lösen Sie eine Idle-Entscheidung aus, sobald das entsprechende Intervall erreicht ist. Zählen Sie keine Frames: Die Frame-Frequenz variiert. In Godot erhält _process(delta) die Zeit seit dem vorherigen Idle-Frame, während _physics_process(delta) den Physik-Ticks folgt; die Dokumentation weist außerdem darauf hin, dass die akkumulierte Delta-Zeit unter bestimmten Bedingungen von realen Sekunden abweichen kann. Node class, Godot documentation

Wählen Sie die Zeitquelle passend zum Verhalten. Kosmetische Bewegungen können in der Regel die verstrichene Zeit pro Frame nutzen. Kollisionsrelevante Bewegungen gehören in das Physik-Update der Engine. Der Timer eines Haustiers für „alle paar Sekunden eine Umgebungsaktion auswählen“ kann einen Simulations-Timer verwenden, Sie sollten jedoch festlegen, was nach einem langen Frame oder einer Pause geschieht: Begrenzen Sie die verstrichene Zeit, führen Sie eine einzelne Entscheidung aus oder holen Sie die Zeit in begrenzten Schritten nach. Ein unbegrenztes Nachholen kann dazu führen, dass das Haustier beim Fortsetzen des Spiels durch zahlreiche Zustände springt.

Abschnitt 5

Gestalten Sie Zustandsübergänge explizit

Erstellen Sie eine kleine Übergangstabelle, bevor Sie weitere Zustände hinzufügen. Zum Beispiel: idle → playing startet eine vom Spieler ausgewählte Aktivität; playing → idle tritt auf, wenn diese endet oder der Spieler sie abbricht; idle → resting kann von der autonomen Routine gewählt werden. Definieren Sie Ein- und Austrittseffekte an einer zentralen Stelle, wie etwa das Starten oder Zurücksetzen eines Timers und die Auswahl der relevanten Animation. Verlassen Sie sich nicht allein auf das Ende einer Animation als Beweis dafür, dass sich der Gameplay-Modus geändert hat: Die visuelle Wiedergabe kann unterbrochen oder übersprungen werden.

Eine Übergangsfunktion sollte den aktuellen Modus validieren, das Modell aktualisieren und ein Ergebnis zurückgeben, das der Renderer darstellen kann. Dadurch wird die Frage, „was das Haustier tut“, von der Frage getrennt, „wie diese Aktion dargestellt wird“. Dies bietet auch Tests ein klares Ziel: Senden Sie einen Befehl, prüfen Sie den resultierenden Modus und verifizieren Sie anschließend, dass die Idle-Routine ihn nicht mehr überschreibt.

Abschnitt 6

Legen Sie fest, wie sich Hintergrundzeit verhalten soll

Es gibt zwei gängige Ansätze, und die richtige Wahl hängt vom Spieldesign ab. Ein rein sitzungsbasiertes Haustier kann die Simulation während einer Unterbrechung anhalten und im vorherigen Zustand fortsetzen. Ein Spiel, bei dem Timer auch im geschlossenen Zustand weiterlaufen sollen, muss eine Referenzzeit speichern und die verstrichene Zeit bei der Rückkehr abgleichen. Betrachten Sie dies als separate Wiederaufnahme-Berechnung, anstatt zu versuchen, den Frame-Loop im Hintergrund auszuführen; Browser-Animations-Callbacks werden bei ausgeblendeten Tabs unter Umständen pausiert. Window.requestAnimationFrame(), MDN

Gleichen Sie bei einem einfachen Haustier nur die Werte ab, die tatsächlich weiterlaufen sollen – beispielsweise einen Aktivitäts-Timer – und setzen Sie eine sinnvolle Obergrenze für das Nachholen. Testen Sie anschließend das Schließen und Wiederöffnen nach einem kurzen und einem langen Intervall. Die Wahl der Uhr, das Verhalten bei Unterbrechungen und die Obergrenze für das Nachholen sind Designentscheidungen; der Frame-Callback einer Engine nimmt Ihnen diese Entscheidungen nicht ab.

Abschnitt 7

Prüfen Sie auf konkurrierende Aktualisierungen und verpasste Eingaben

Testen Sie den Loop anhand einiger reproduzierbarer Szenarien: Lassen Sie das Spiel für mehrere Intervalle im Leerlauf; erteilen Sie kurz vor einer Idle-Entscheidung einen Befehl; halten Sie eine Eingabe gedrückt oder wiederholen Sie sie; pausieren Sie das Spiel und setzen Sie es fort; und lösen Sie eine neue Aktion aus, während eine Animation noch abgespielt wird. Stellen Sie sicher, dass jeder Befehl das Modell genau einmal ändert, Idle-Logik einen vom Spieler gewählten Zustand nicht überschreibt und das Verhalten der verstrichenen Zeit der gewählten Pausen-Strategie entspricht.

Wenn Sie einen festen Aktualisierungsschritt für die Simulation verwenden, beachten Sie, dass dieser zwischen gerenderten Frames null, einmal oder mehrmals ausgeführt werden kann. Unity dokumentiert dieses Verhalten für FixedUpdate und empfiehlt es für Physikberechnungen; Eingaben und visuelle Updates unterliegen anderen zeitlichen Anforderungen. FixedUpdate(), Unity documentation Das Input System von Unity reiht Geräte-Events zudem in eine Warteschlange ein und verarbeitet sie entsprechend dem konfigurierten Aktualisierungsmodus. Stimmen Sie die Eingabeverarbeitung daher auf den Loop ab, der diese Befehle verarbeitet. Input event queue, Unity Input System

Abschnitt 8

Eine praktische Trennung, die sich lohnt

Halten Sie die Architektur schlank: ein gemeinsames Haustier-Modell, ein Pfad von der Eingabe zum Befehl, ein Update für das Idle-Verhalten, eine explizite Übergangsfunktion und ein Renderer, der das Modell ausliest. Fügen Sie einen festen Simulationsschritt nur dann hinzu, wenn zeitkritische Verhaltensweisen dies erfordern; machen Sie nicht jede Animation oder Umgebungsentscheidung von Physik-Ticks abhängig. Wenn ein Fehler auftritt, prüfen Sie, wer den Modus zuletzt geändert hat und welche Uhr ihn vorangetrieben hat. So erhält jedes Update eine eindeutige Aufgabe, und das Idle- sowie das interaktive Verhalten bleiben vorhersehbar, wenn das Haustier weitere Aktionen hinzugewinnt.

Abschnitt 9

Quellen

Weitere Artikel

Dieses Thema weiter erkunden