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:
MovementSystem
muss die Grenzen derWorld
Komponente kennen, damit sie weiß, wann sie auf die andere Seite des Bildschirms umbrochen werden mussLevelSystem
muss dieGameState
Komponente kennen, damit sie weiß, ob sie neue Asteroiden erzeugen sollInputSystem
muss den Status derKeyboard
Komponente 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, EntityManager
nach "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?
quelle
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".
quelle
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.
MovementSystem
Sie können sich einfach beim Event-Manager für das Event registrieren.WorldComponentCreatedEvent
Wenn Sie Ihre Weltkomponente erstellen,MovementSystem
erhält das Event das Ereignis, das als Ereignisdaten einen Verweis auf die Welt enthalten kann.quelle