Modellierung von „Singletons“ in einem Entity-Component-System

7

Ich schreibe eine grundlegende Asteroids-Implementierung als Übung, um zu lernen, wie man in Entitäten und Komponenten denkt, und das meiste davon ist ziemlich einfach. Aber eine Sache, auf die ich immer wieder stoße, sind Situationen, in denen ein bestimmtes System eine bestimmte Entität / Komponente benötigt und ich weiß, dass es immer nur eine davon gibt. Beispiele:

  • MovementSystemmuss die Grenzen der WorldKomponente kennen, damit sie weiß, wann sie auf die andere Seite des Bildschirms umbrochen werden muss
  • LevelSystemmuss die GameStateKomponente kennen, damit sie weiß, ob sie neue Asteroiden erzeugen soll
  • InputSystemmuss den Status der KeyboardKomponente kennen

(usw.)

Das von mir verwendete ECS ist handgerollt, ähnelt jedoch konzeptionell dem Entity System RDBMS Beta - Java von Adam Martin . Was ich in Fällen wie den oben genannten wiederholt mache, ist, EntityManagernach "allen" Komponenten des angegebenen Typs zu fragen und die "erste" (auch bekannt als nur) zu nehmen:

World world = entityManager.getAllComponentsOfType(World.class).iterator().next()

Dies funktioniert, scheint aber klobig und macht den Code ärgerlich nicht offensichtlich. Alternativen, an die ich gedacht habe:

  • Machen Sie jede Systemschleife über 'alle' dieser Komponenten, genau wie bei jedem anderen Komponententyp
  • Fügen Sie dem explizite Unterstützung für 'Singleton'-Komponenten hinzu EntityManager
  • Verwenden Sie für diese Dinge keine Komponenten. Injizieren Sie sie auf andere Weise in die Systeme und leben Sie damit, dass das Design dadurch deutlich weniger rein wird

Gibt es eine typische oder bekannte Lösung für dieses Problem?

David Moles
quelle

Antworten:

14

Denken Sie daran, sich nicht von Entitäten und Komponenten mitreißen zu lassen. Es ist völlig in Ordnung zu nicht Ihr haben Worldals Bestandteil. Wenn Sie sicher sind, dass es nur eines von etwas geben wird, macht es wenig Sinn, es zu einer Komponente zu machen. Komponenten können in zahlreichen Entitäten zusammen mit anderen Komponenten wiederverwendet werden.

Dies macht das Spiel nicht weniger rein, es macht den Code sauberer. Entitätssysteme sind nur ein Werkzeug für einen Teil Ihres Spiels. Es muss nicht alles umfassen, um ein gutes System zu sein. Verwenden Sie es nur dort, wo es für Sie sinnvoll ist .

MichaelHouse
quelle
2
Wirklich gute Antwort. Denken Sie am Ende des Tages daran, wenn Sie Ihr Spiel nicht beenden, wird es niemand spielen. Tun Sie, was funktioniert, um die Arbeit zu erledigen.
Wes
4
+1 Nur weil du einen Hammer hast, heißt das nicht, dass alles ein Nagel ist =)
Patrick Hughes
1

Wie andere bereits gesagt haben, müssen Singletons nicht als Komponenten implementiert werden. Das Speichern dieser Daten direkt in den Systemen oder einer externen Singleton-Klasse ist in Ordnung, solange nur Systeme darauf zugreifen. Wenn Sie Ihr Design jedoch wirklich "rein" halten möchten (dies vereinfacht die Serialisierung des gesamten Spielstatus erheblich, wenn sich beispielsweise alle Daten in Komponenten befinden), sollten Sie ein statisches Feld oder einen Getter direkt in der Komponente verwenden, z. B. "World" .Beispiel".

Maroy
quelle
0

Eine Möglichkeit, dies zu tun, besteht darin, ein Nachrichtensystem in Ihrer Anwendung zu implementieren. Sie können dann Ereignisse beim Erstellen bestimmter Komponenten generieren.

MovementSystemSie können sich einfach beim Event-Manager für das Event registrieren. WorldComponentCreatedEventWenn Sie Ihre Weltkomponente erstellen, MovementSystemerhält das Event das Ereignis, das als Ereignisdaten einen Verweis auf die Welt enthalten kann.

ed4053
quelle
Ein Nachrichtensystem ist für einige Dinge eine gute Idee, aber hier sollten diese "Singletons" wahrscheinlich keine Komponenten von Entitäten sein
ThorinII