Meine Frage ist:
Wie kann ich mit Spielzuständen in meinem Entitätssystem umgehen, ohne einen Stapel von Spielzustandsobjekten zu behalten?
Wenn sich eine Entität beispielsweise für Eingabeereignisse registrieren muss, ruft die Eingabekomponente das Eingabesystem auf und sagt "Diese Entität für diese Eingabe registrieren". Dies ist alles in Ordnung, aber wenn Sie das Konzept der Spielzustände hinzufügen (sagen wir einen Pausenbildschirm), wird es zu einem Problem, herauszufinden, ob sich eine Entität im aktuellen Zustand befindet und die Eingabe erhalten sollte.
Ich könnte die Eingabekomponente / das Eingabesystem so erweitern, dass dort steht: "Diese Entität für diese Eingabe registrieren, während sie sich in diesen Spielzuständen befindet". Dies setzt jedoch voraus, dass jede Entität weiß, in welchen Zuständen sie verwendet wird, und das ist möglicherweise nicht offensichtlich. Außerdem klingt es nicht effizient, eine Liste der Spielzustände für jeden registrierten Eingang (und für andere Systeme, die Rückrufe verwenden) zu führen.
Eine andere Idee, die ich hatte, ist, dass es eine Entität geben wird, die den Spielstatus darstellt, diese als deaktiviert markiert und dann beim Generieren des Eingabeereignisses überprüft, ob die Entität kein Abkömmling einer deaktivierten Spielstatus-Entität ist. Es scheint teuer zu sein, den Elternteil für jeden Rückruf zu ermitteln.
Eine andere Idee ist, dass alle Systeme ihre Daten mit dem aktuellen Status abspeichern. Auf diese Weise wird die Zielentität beim Generieren der Eingabe nicht einmal ein Kandidat sein. Dies schadet jedoch wirklich der Möglichkeit, die Kommunikation zwischen Entitäten in verschiedenen Zuständen zuzulassen (nicht so sehr ein Problem für Pausenbildschirme, sondern das Aufheben von Sperren in Oblivion / Skyrim).
Die einzige andere Idee, die ich hatte, ist, dass alle Komponenten Zustandsänderungsereignisse verarbeiten und mit ihrem jeweiligen System kommunizieren, um alles zu deaktivieren, was sie registriert haben, und es wieder zu aktivieren, wenn sie in diesen Zustand zurückkehren.
Das zweite (ein Objekt als deaktiviert markieren) und vierte (jede Komponente muss sich mit Zustandsänderungen befassen) scheinen meine besten Ideen zu sein, aber keine von ihnen spricht mich als besonders großartig an.
Hat jemand andere Ideen, wie man das macht?
Bearbeiten Während ich in dieser Frage speziell über Eingaben spreche, kann dies jedes System bedeuten, das Nachrichten / Ereignisse an Entitäten senden kann, wie z. B. Kollisionen, Timer-Ereignisse usw.
quelle
Antworten:
Was häufig verwendet wird, ist ein Zwischenprodukt,
Intent System
das die Eingabe abstrahiert und den Kontext und die relevanten Spielzustände verfolgt.Das Intent-System beendet die Übertragung von Eingaben, wenn die Simulation beispielsweise angehalten wird. Es behandelt auch die Zuordnung zwischen Controller-Ereignissen und Absichten (in Richtung bewegen, rennen, schießen, neu laden ...).
Auf diese Weise sind Ihre anderen Komponenten nicht von bestimmten Gamepads / Eingaben abhängig (BUTTON_A, BUTTON_B vs BUTTON_X, BUTTON_O ...), sondern reagieren alle auf die gleichen Absichten (IntentRun, IntentReload ...).
Ein weiterer Vorteil ist, dass das Intent-System erkennt, dass verfügbare Controller hinzugefügt / entfernt werden, da es Intents an jeden Teilnehmer senden kann, auch außerhalb der Simulation, die Sie für Intents verwenden können
AddPlayer(controllerID)
.Wie viele Informationen über den Spielstatus Sie dem System entweder über Ereignisse / Nachrichten oder direkt zur Verfügung stellen, bleibt Ihnen überlassen. Aber die Zeit, die in das Intent-System investiert wird, lohnt sich normalerweise.
Sie können Absichtskontexte verwalten, die Absichten generieren, wenn sie mit dem System verbunden werden.
Der Kontext kann priorisiert werden, dh:
Auf diese Weise können Sie die aktuell relevanten Kontexte hinzufügen und entfernen.
Und eine Sache bei den gesamten Vorsatzsystemen ist, dass sie ausgeführt werden sollten, während die Simulation angehalten ist.
Eine Möglichkeit, die häufig verwendet wird, um die Spielsimulation zu spielen / anzuhalten, ohne nicht mit der Simulation in Zusammenhang stehende Aktualisierungen zu unterbrechen, besteht darin, unterschiedliche Zeitspannen zu verwenden. dh
GenericSystem::onTime(Long time, Long deltaTime, Long simTime, Long simDeltaTime)
.Mit diesem Ansatz kann Ihre Engine einfach die Inkremente in der SimTime des Spiels blockieren, was wiederum Aktualisierungen der relevanten Animations- und Physik-Engines blockiert und
simTime and simDeltaTime
gleichzeitig kontinuierliche Aktualisierungen Ihres Kamera -Federeffekts ermöglicht, wenn er sich auch während der Pause, der Animation von, bewegen muss der Ladeeffekt auf einer virtuellen In-Game-Werbetafel, während Daten heruntergeladen werden ...quelle
Wie wäre es mit der Erstellung eines globalen Ereignissystems und einer Ereignis-Listener-Komponente für jede Entität? Nach einem Event "Game State Change" konnte man für jede Entität individuell mit Komponenten experimentieren.
Angenommen, Sie haben eine Eingabekomponente. Nachdem die Ereignis-Listener-Komponente das Spielstatusänderungsereignis empfangen hat, ändert sie sehr spezifische Werte für diese bestimmte Eingabekomponente, sodass sie keine Eingabeaufrufe empfängt oder keine Bewegungs- oder Antwortaufrufe an das System oder dessen Besitzer ausführt.
Dies funktioniert bei mir, da die meisten meiner Komponenten per Skript (über Lua) erstellt wurden. Das heißt, ich habe eine Eingabekomponente, die einmal ausgelöst wird, wenn eine Taste gedrückt wird und eine Bewegung + Richtung ausgelöst wird, und dann ausgelöst wird, wenn die Taste losgelassen wird und eine Stop + Richtung ausgelöst wird. Es gibt auch eine Ereignis-Listener-Komponente, die die Eingabekomponente kontaktiert (wenn das Spiel unterbrochen ist), um das Auslösen von Funktionen zu stoppen und erforderlichenfalls anzuhalten. Ich könnte dann leicht eine andere Entität mit einer anderen Reaktion auf dieselben Ereignisse und Tastendrücke unter Verwendung eines anderen Skripts hinzufügen. Auf diese Weise können Sie die Interaktion zwischen verschiedenen Entitäten in verschiedenen Zuständen speichern und sogar noch anpassbarer gestalten. Darüber hinaus enthalten einige Entitäten möglicherweise nicht einmal die Ereignis-Listener-Komponente.
Was ich gerade erklärt habe, ist im Grunde genommen ein praktisches Beispiel für Ihre vierte Lösung.
quelle