2010-10-18 4 views
7

Ich erstelle eine component-based game object system. Einige Tipps:Spielobjekt-Komponenten in Spiel-Subsystemen registrieren? (Component-based Game Object Design)

  1. GameObject ist einfach eine Liste von Components.
  2. Es gibt GameSubsystems. Zum Beispiel, Rendering, Physik usw. Jede GameSubsystem enthält Zeiger auf einige von Components. GameSubsystem ist eine sehr mächtige und flexible Abstraktion: Sie repräsentiert jeden Abschnitt (oder Aspekt) der Spielwelt.

Es besteht ein Bedarf an einem Mechanismus von Components in GameSubsystems Registrierung (wenn GameObject erstellt und zusammengesetzt). Es gibt 4 nähert sich:


  • 1: Chain of responsibility Muster. Jede Component wird jedem GameSubsystem angeboten. GameSubsystem trifft eine Entscheidung, welche Components registriert (und wie man sie organisiert). Zum Beispiel kann GameSubsystemRender Renderable Components registrieren.

pro. Components wissen nichts darüber, wie sie verwendet werden. Geringe Kopplung A. Wir können neue GameSubsystem hinzufügen. Zum Beispiel fügen wir GameSubsystemTitles hinzu, das alle ComponentTitle registriert und garantiert, dass jeder Titel eindeutig ist und eine Schnittstelle zum Abfragen von Objekten nach Titel bietet. Natürlich sollte ComponentTitle in diesem Fall nicht neu geschrieben oder vererbt werden. B. Wir können bestehende GameSubsystems reorganisieren. Zum Beispiel können GameSubsystemAudio, GameSubsystemRender, GameSubsystemParticleEmiterer in GameSubsystemSpatial eingebunden werden (um alle Audio, Emitter, Render Components in der gleichen Hierarchie zu platzieren und Eltern-relative Transformationen zu verwenden).

con. Jeder für jeden Scheck. Sehr ineffizient.

con. Subsystems über Components wissen.


  • 2: Jeder Subsystem sucht nach Components bestimmten Arten.

pro. Bessere Leistung als in Approach 1.

con. Subsystems noch über Components wissen.


  • 3: Component selbst Register in GameSubsystem(s). Wir wissen zur Kompilierungszeit, dass es einen GameSubsystemRenderer gibt, also wird ComponentImageRender so etwas wie GameSubsystemRenderer :: register (ComponentRenderBase *) aufrufen.
    Observer Muster. Component abonniert "update" -Ereignis (gesendet von GameSubsystem(s)).

pro. Performance.Keine unnötigen Kontrollen wie in Approach 1 und Approach 2.

con. Components sind schlecht mit GameSubsystems gekoppelt.


  • 4: Mediator Muster. GameState (das GameSubsystems enthält) kann RegisterComponent (Component *) implementieren.

pro. Components und GameSubystems wissen nichts voneinander.

con. In C++ würde es wie hässlicher und langsamer Typid-Schalter aussehen.


Fragen: Welcher Ansatz ist besser und vor allem in komponentenbasierten Design verwendet? Welche Praxis sagt? Irgendwelche Vorschläge zur (datengesteuerten) Implementierung von Approach 4?

Vielen Dank.

Antwort

2

Vote für den dritten Ansatz.

Zur Zeit arbeite ich auf komponentenbasierte Spiel Objektsystem und i eindeutig einige zusätzliche Vorteile dieses Ansatzes sehen:

  • Die Komponente mehr und mehr selbstgenügsam Sub-Entität ist, da es nur auf ein abhängt Satz verfügbarer Subsysteme (ich nehme an, dass dieser Satz in Ihrem Projekt festgelegt ist).

  • Datengesteuerter Entwurf ist anwendbarer. Idealerweise können Sie auf diese Weise ein System entwerfen, in dem Komponenten vollständig in den Daten, nicht aber in C++ definiert sind.


EDIT: Ein Merkmal dachte ich über, während auf CBGOS arbeiten. Manchmal ist es bequem, die Fähigkeit zu haben, subsystemlos passive Komponenten zu entwerfen und zu konstruieren. Wenn Ihnen das einfällt, ist der vierte Weg der einzige Weg.

+0

Ich stimme Ihnen zu, dass diese Vorteile sehr wertvoll sind. Aber die erste hat eine andere Seite: keine "Komponenten" Wiederverwendbarkeit zwischen Projekten (mit verschiedenen Gruppen von "Subsystemen").Die Neuzusammensetzung von Teilsystemen in einem einzigen Projekt wird ebenfalls zu einem Problem. Es kann Hunderte von 'Komponenten' geben, deren Umschreiben alles eine langweilige Aufgabe ist. Ich glaube, dass dieser zweite Vorteil auch in anderen Ansätzen erreicht werden kann. –

+0

Stimmen Sie mit Ihrem Punkt überein. Zu einer Zeit bin ich mit CBGOS Design nicht so viel vorgestellt, wie ich es wünsche. Aber die Arbeit, die ich damit zu tun hatte, brachte mich zu folgenden Überlegungen: * 1. * Design-Subsystem-Schnittstellen auf die abstrakteste Art und Weise, so dass die Menge der Subsysteme sich leicht über verschiedene Projekte hinweg ändern würde. * 2. * Bevorzugen Sie die Nachrichteninteraktion zwischen Komponenten vor allem und schneiden Sie Schnittstellenabhängigkeiten aus, wo es möglich ist. – Keynslug

+0

Es kann funktionieren. Ich habe Leute in den Foren von gamedev.net getroffen, die diesen Ansatz auch verwenden. –

1

Mein Ansatz war, das Proxy-Muster innerhalb jedes Subsystems zu implementieren. Da jedes Subsystem nur an einer Teilmenge der Gesamtkomponenten interessiert ist, die jede Entität enthalten kann, speichert der Proxy Zeiger auf nur die Komponenten, um die sich das System kümmert, z. B. ein Achssystem kümmert sich nur um Position und Geschwindigkeit und benötigt daher einen Proxy, der speichert zwei Zeiger auf diese Komponenten. Wenn die Entität eine oder mehrere dieser Entitäten nicht enthält, wird sie vom Subsystem ignoriert. Wenn beide Komponenten vorhanden sind, wird ein Proxy-Knoten erstellt und einer internen Sammlung hinzugefügt. Es ist auch nützlich, dass der Proxy den eindeutigen Bezeichnerwert für die Entität speichert, so dass Proxies in konstanten Zeiten von jedem Subsystem hinzugefügt/entfernt werden können, falls es notwendig sein sollte.

Sollte eine Entität aus der Engine entfernt werden müssen, kann eine einzelne Nachricht mit der ID der Entität an jedes Subsystem gesendet werden. Der Proxy kann dann unabhängig von jeder Subsystem-Sammlung entfernt werden.

+0

Guter Ansatz, Ian. –

Verwandte Themen