Entität als Aggregation erstellen


10

Ich habe kürzlich gefragt, wie Entitäten von ihrem Verhalten getrennt werden sollen, und die Hauptantwort, die mit diesem Artikel verknüpft ist: http://cowboyprogramming.com/2007/01/05/evolve-your-heirachy/

Das ultimative Konzept, über das hier geschrieben wurde, ist das folgende: OBJEKT ALS REINE AGGREGATION.

Ich frage mich, wie ich mit C # Spielentitäten als reine Aggregation erstellen könnte. Ich habe das Konzept, wie dies funktionieren könnte, noch nicht ganz verstanden. (Vielleicht ist die Entität ein Array von Objekten, die eine bestimmte Schnittstelle oder einen bestimmten Basistyp implementieren?)

Mein derzeitiges Denken beinhaltet immer noch eine konkrete Klasse für jeden Entitätstyp, die dann die relevanten Schnittstellen (IMoveable, ICollectable, ISpeakable usw.) implementiert.

Wie kann ich eine Entität nur als Aggregation erstellen, ohne einen konkreten Typ für diese Entität zu haben?


Wenn Sie immer noch interessiert sind, kann ich Ihnen mein kleines Entitätssystem in C # senden. Es ist nicht erstaunlich , aber es funktioniert.
Die kommunistische Ente

Antworten:


6

Der von West in diesem verlinkten Artikel beschriebene Ansatz der "reinen Aggregation" meidet ein "Entitäts" -Objekt insgesamt. Es gibt Komponenten, die im Speicher herumschweben, aber wenn überhaupt, nur durch implizite Beziehungen miteinander verbunden sind.

Ein Weg, dies zu tun, ist ein sogenannter Außenborder-Ansatz . In einem solchen System werden Komponenten von Systemen gehalten, die sie verwalten oder auf andere Weise steuern (ich verwende hier den Begriff "verwalten", aber Sie sollten dies nicht so verstehen, dass ich vorschlage, dass Sie eine Reihe von * Manager-Klassen halten müssen Komponententypen). Zum Beispiel kann Ihr Physiksystem an einer Reihe von Dingen festhalten, die jeden starren Körper in seiner Simulationswelt darstellen, und diese Dinge als Physikkomponenten ausstellen. Die Komponenten können die tatsächlichen Objekte sein, die von dem betreffenden Subsystem verarbeitet werden, oder sie können je nach Bedarf Proxys für diese Objekte sein.

In einem solchen System muss eine "Entity" -Klasse nicht unbedingt eine Sammlung von Verweisen auf die Komponenten enthalten, aus denen sie besteht. Stattdessen wird eine Benachrichtigung über die Erstellung oder Zerstörung einer "Entität" ausgegeben, und jedes Subsystem, das Komponenten verarbeitet, überprüft die Beschreibung der erstellten / zerstörten Entität (die normalerweise aus einigen Daten geladen wird) und bestimmt, ob eine Komponente dafür erforderlich ist.

Einer der Vorteile dieses Ansatzes besteht darin, dass Sie für jede Komponente eine wirklich gute Referenzlokalität erhalten. Leider ist es insgesamt etwas seltsam und nicht die freundlichste Variante komponentenbasierter Entitäten, die mir begegnet sind. Manchmal ist es sehr praktisch, ein reales Objekt zu haben, das eine Entität darstellt, selbst wenn dieses Objekt nur schwache Verweise auf Komponenten zusammenfasst, die noch von anderen Subsystemen gehalten werden (wenn nichts anderes, bietet es eine einfache Möglichkeit, Nachrichten zwischen Komponenten weiterzuleiten). .

Es gibt mehrere gute Möglichkeiten, komponentenorientierte Spielobjektsysteme zu implementieren. Es hilft wirklich, wirklich, wirklich , wenn Sie eine solide Vorstellung von den Anforderungen haben, die Sie an Ihr System stellen möchten. Sie können sich beispielsweise ansehen, was beliebte Frameworks wie Unity tun. Ohne strenge Anforderungen an sich selbst zu stellen, könnten Sie auf das Problem stoßen, das System endlos zu "entwerfen", ohne es jemals wirklich zu bauen, und vergeblich versuchen, die perfekte Implementierung zu finden. Aus irgendeinem Grund habe ich dies bei Komponentensystemen oft gesehen.


3

So wie Unity es macht, stammen alle Skripte (in Ihrem Fall Spielcode, der für einen bestimmten Spielobjekttyp spezifisch ist) von einer Basisklasse MonoBehaviour, die sich selbst von der für Ihren Fall relevanteren Klasse ableitet Component. Sie bearbeiten die GameObject-Klasse niemals (und haben keinen Zugriff auf den Code von).

Das Spielobjekt ist dafür verantwortlich, alle diese Components zu enthalten. Es ist angeblich auch dafür verantwortlich, die relevanten Funktionen auf sie aufzurufen (dh Update). Unity verwendet Reflection, um zu bestimmen, welche Funktionen aufgerufen werden sollen (siehe Abschnitt "Überschreibbare Funktionen" auf dieser Seite ), aber Sie möchten sie wahrscheinlich virtuell machen.

Einer der Mechanismen, die Sie in Unity verwenden, besteht darin, Komponenten für Ihr aktuelles Spielobjekt (oder seine untergeordneten Objekte) nach Typ abzurufen. Es gibt einige Hilfseigenschaften, die einige der gängigen Dinge einschließen. Wenn Sie beispielsweise auf die TransformKomponente des Spielobjekts zugreifen möchten (um die Position / Drehung / Skalierung des Spielobjekts zu steuern), müssen Sie normalerweise so etwas tun this.GetComponent<Transform>().position, aber das wird in einen Hilfsaufruf eingeschlossen this.transform.position. Ein weiteres häufiges Muster ist der Zugriff auf die RendererKomponente des aktuellen Spielobjekts . Wenn Sie also beispielsweise das Material des aktuellen Spielobjekts ändern möchten, können Sie in einem anderen Skript etwas Ähnliches tun this.renderer.material = someOtherMaterialund Ihr Spielobjekt entsprechend aktualisieren.

In Unity funktioniert dies unter anderem dadurch, dass der Editor so eingerichtet ist, dass Sie in Ihrer Szene Spielobjekte erstellen können, an denen bereits Komponenten angeschlossen sind. Im Fall von Unity haben alle Spielobjekte eine TransformKomponente, sie können jedoch auch integrierte Typen wie AudioListeneroder enthalten Renderer, die das tun, was Sie erwarten würden. Oder Sie können Ihre eigenen Komponenten hinzufügen, die alles tun, was Sie möchten. Der Editor macht auch öffentliche / serialisierbare Felder auf Ihren Komponenten verfügbar, sodass Sie keine unterschiedlichen Skripte erstellen müssen, wenn Sie denselben Basiscode verwenden möchten, aber einige magische Zahlen ändern möchten.

Alles in allem ist es ziemlich raffiniert, und ich würde vorschlagen, die kostenlose Version von Unity herunterzuladen und damit herumzuspielen, wie das Skriptsystem eingerichtet ist, um einen ziemlich anständigen Proof of Concept für das zu erzielen, was Sie erreichen möchten.


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.