Wie gehe ich in einer Entity-Component-System-Engine mit Gruppen abhängiger Entitäten um?

47

Nachdem ich ein paar Muster für das Game-Design durchgesehen habe, habe ich mich mit dem Entity-Component-System (ES-System) für meine Game-Engine abgefunden. Ich lese Artikel (hauptsächlich T = Machine ) und überprüfe Quellcode. Ich glaube, ich habe genug, um loszulegen.

Es gibt nur eine Grundidee, mit der ich zu kämpfen habe. Wie gehe ich mit Gruppen von Entitäten um, die voneinander abhängig sind?

Lassen Sie mich ein Beispiel verwenden:

Angenommen, ich mache einen Standard-Overhead-Shooter (denken Sie an Jamestown ) und möchte eine "Boss-Einheit" mit mehreren unterschiedlichen, aber verbundenen Teilen aufbauen. Die Aufteilung könnte ungefähr so ​​aussehen:

  • Schiffskörper: Bewegung, Rendering
  • Kanone: Position (relativ zum Schiffskörper verriegelt), Tracking \ Fire at hero, Schaden nehmen, bis deaktiviert
  • Core: Position (relativ zum Schiffskörper gesperrt), Tracking \ Fire at hero, Schaden erleiden bis deaktiviert, Deaktivieren (er ... zerstören) aller anderen Einheiten in der Schiffsgruppe

Mein Ziel wäre etwas, das als eigenständiges Spielelement identifiziert (und manipuliert) würde, ohne jedes Mal, wenn ich ein neues aggregiertes Element erstellen möchte, das Subsystem von Grund auf neu schreiben zu müssen.

Wie implementiere ich diese Art von Design in ES System?

  1. Implementiere ich eine Art Eltern-Kind-Beziehung (Entitäten können Kinder haben)? Dies scheint der Methodik zu widersprechen, dass Entities nur leere Container sind und es sich mehr OOP anfühlt.
  2. Implementiere ich sie als separate Entitäten mit einer Art verbindender Komponente (BossComponent) und zugehörigem System (BossSubSystem)? Ich kann nicht anders, als zu glauben, dass dies schwer umzusetzen sein wird, da die Kommunikation der Komponenten eine große Bärenfalle zu sein scheint.
  3. Implementiere ich sie als eine Entität mit einer Sammlung von Komponenten (ShipComponent, CannonComponents, CoreComponent)? Diese scheint sich von der Absicht des ES-Systems zu unterscheiden (Komponenten hier scheinen zu schwergewichtigen Entitäten zu ähneln), aber ich weiß das, also habe ich mir gedacht, dass ich das da rausstellen würde.
  4. Implementiere ich sie als etwas anderes, das ich erwähnt habe?

Ich weiß, dass dies in OOP sehr einfach implementiert werden kann, aber ich werde mich an die Wahl von ES gegenüber OOP halten. Wenn ich mit der reinen ES-Theorie brechen muss, um dieses Design zu implementieren, werde ich (nicht wie ich vorher keine Kompromisse beim reinen Design eingehen musste), aber ich würde es vorziehen, dies aus Leistungsgründen zu tun, anstatt mit einem schlechten Design zu beginnen.

Denken Sie für zusätzliche Gutschriften an dasselbe Design, aber jede der "Boss-Entitäten" war tatsächlich mit einer größeren "BigBoss-Entität" verbunden, die aus einem Hauptkörper, einem Hauptkern und drei "Boss-Entitäten" bestand. Damit würde ich eine Lösung für mindestens 3 Dimensionen finden (Großeltern-Eltern-Kind) ... die für mich mehr als genug sein sollte.

John Daniels
quelle
2
Es sind einfach verschiedene Maschenteile, die an eine Entität gebunden sind, Schiffs- und Kanonennetz, die an die Boss-Entität gebunden sind, und nicht überentwickeln. Übrigens ist ein Entity-Component-System OOP!
Maik Semder
2
Ja - das Schlimmste an diesen T-Machine-Artikeln ist die falsche Vorstellung, dass dies irgendwie nicht objektorientiert ist. Die meisten Komponentensysteme für Entitäten sind vollständig objektorientiert, jedoch nicht vererbungsbasiert.
Kylotan
3
Ich denke, sie betonen die Nicht-OOP-Natur, weil "klassisches OOP denken" Sie in so große Schwierigkeiten bringen wird. Bisher habe ich einigen Leuten beim Einstieg in Entity-Systeme geholfen, und das ist die größte Hürde. Der Versuch, Code in die Komponenten einzufügen, Komponenten zu haben, die untereinander eine Unterklasse bilden usw. ist zunächst ein großes Problem, aber es ist schön zu sehen, dass das Licht aufleuchtet, wenn die Idee endlich vollständig erfasst ist.
PSpeed
@MaikSemder Ich habe meine Kommentare bereinigt und in den Chat
MichaelHouse
1
Nur damit ich @MaikSemder verstehe, kann eine Entität im ES-System, auf das Sie verweisen, mehrere Komponenten desselben Typs haben, und das für diese Komponenten zuständige Subsystem müsste sich mit dieser Tatsache befassen? Eine Entität kann also mehrere Renderkomponenten haben, und die Daten und Subsysteme dieser Komponenten bestimmen, wie sie jeweils richtig gerendert werden sollen. Das würde zu weniger Entitäten, möglicherweise weniger Komponenten, aber einer etwas tieferen Subsystemlogik führen, richtig?
John Daniels

Antworten:

41

Wenn ich in dieser Situation wäre, würde ich jeden Teil des Chefs als separate Einheit erstellen. Diese "Untereinheiten" würden irgendeine Art von AttachmentPointoder ParentEntityKomponente enthalten. Diese Komponente würde einen Verweis auf die übergeordnete Entität und einen Versatz von der übergeordneten Position enthalten. Beim Aktualisieren der Position überprüfen sie die übergeordnete Position und wenden den Versatz an, um ihre eigene Position zu generieren. Darüber hinaus kann überprüft werden, ob die übergeordnete Entität noch vorhanden ist. Darüber hinaus können Sie eine SubEntityKomponente haben, die das Vorhandensein von Unterentitäten für die übergeordnete Entität verfolgt. Auf diese Weise können Sie beispielsweise nur den Kern des Bosses angreifbar machen, wenn die Waffen mit den Schilden zerstört werden.

Momentan verwende ich eine TargetEntityKomponente in meinem Spiel, die zum Verfolgen von Geschützen und zum Aufheben von Ressourcen durch Goblins verwendet wird. Es kann die Position der Zieleinheit überprüfen und ihr Verhalten entsprechend ändern. Entitäten, die keine Position haben, werden niemals als Ziel hinzugefügt, daher gibt es dort keine Sorgen. Wenn Sie jedoch eingehender werden möchten, z. B. die Integrität der über- oder untergeordneten Entität, den Schild, die Leistungsreserven oder was auch immer, müssen Sie sicherstellen, dass die über- oder untergeordnete Entität tatsächlich über die zugehörige Komponente verfügt.

Wenn Sie jedes Teil zu einer eigenen Entität machen, bleibt die Flexibilität des Entitäts- / Komponenten-Frameworks erhalten, indem Sie jedem Teil des Chefs zusätzliche und unterschiedliche Komponenten hinzufügen können. Beispielsweise könnte ein Teil des Chefs eine Waffenkomponente und eine Gesundheitskomponente haben, während ein anderer Teil eine Schildkomponente und eine Gesundheitskomponente hätte.

Ich habe hier eine weitere Diskussion zu diesem Thema gefunden . In diesem Fall diskutieren die Benutzer das Hinzufügen mehrerer Komponenten desselben Typs zu einer Entität (was für mich eine schlechte Idee ist). Es scheint ein nützliches Gespräch zu sein, obwohl ich nicht die ganze Diskussion gelesen habe.

MichaelHouse
quelle
Viele gute Informationen hier. Sie haben die Lösung gut erklärt, mir ein Beispiel gegeben und wahrscheinlich 1 oder 2 weitere Fragen beantwortet, auf die ich später hätte zurückkommen müssen. Die verknüpfte Diskussion scheint auch faszinierend zu sein, besonders wenn ich anfange, mich schwieriger umzusetzen. Vielen Dank @ Byte56!
John Daniels
Kein Problem, John! Natürlich gibt es viele verschiedene Möglichkeiten, ein EC-System zu implementieren. Das System, an das ich bei dieser Antwort gedacht habe, ist das, das ich in dieser Antwort beschrieben habe . Viel Glück mit deinem Spiel!
MichaelHouse
Ihr Ansatz ist am flexibelsten und es ist sinnvoll, ihn in einer allgemeinen Spiel-Engine zu verwenden.
Coyote
7

Ohne zu viele Details über Ihre vorhandenen Systeme zu kennen, würde ich dies (und dies zu einem gewissen Grad in meinem eigenen Entitätssystem) durch eine Komponente wie AttachedTo (parentEntity) modellieren. Jedem der Kinder kann dann die AttachedTo (Chef) -Komponente zugewiesen werden.

Das Rendering-System (oder was auch immer) greift dann nach Entitäten mit folgenden Komponenten: Position, AttachedTo usw. und bildet die richtigen Hierarchien.

PSpeed
quelle
Dies scheint die Konsensantwort zu sein. Das nächste Mal werde ich weitere Implementierungsdetails zum Kauen bereitstellen. Vielen Dank @PSpeed!
John Daniels
4

Wenn Sie möchten, dass eine Entität nur durch eine ID dargestellt wird, können Sie die Entitäten über eine spezielle Komponente einschließen. Sie könnten es CompositeComponent nennen, und dies enthält eine Liste von untergeordneten Entitäts-IDs und Schnittstellen zum Hinzufügen / Entfernen von untergeordneten Elementen aus dieser Liste.

Offensichtlich müssen alle Komponenten, die von der Position usw. abhängen, mit dieser zusammenarbeiten, um die Entität richtig zu platzieren. Wie dies implementiert wird, hängt etwas davon ab, wie Sie die Positionierung aktuell implementieren.

Übrigens gibt es keine "reine ES-Theorie" - Entitäten aus Komponenten zu machen, ist ein beliebter Ansatz, aber die genaue Methode ist noch keineswegs standardisiert.

Kylotan
quelle
Ja, ich sollte lernen, das Wort "pur" in keiner Designdiskussion zu verwenden ... so etwas gibt es nicht. ConpositeComponent-Route scheint hier der Konsens zu sein. Vielen Dank @Kylotan!
John Daniels