Entity Component System - Wie implementiere ich die Transformation eines Objekts?


11

Beim Entwerfen eines Entity-Component-Systems für meine Engine bin ich auf einen kleinen Haken beim Speichern und Abrufen eines bestimmten Komponententyps gestoßen.

Lassen Sie mich zunächst einige Begriffe festlegen, die ich in dieser Frage verwenden werde:

  • Ich nenne " Komponente " eine Datenstruktur, die relevante Daten für ein bestimmtes System speichert.
  • Ich nenne " System " eine Ansammlung von Methoden und Datenstrukturen, die Komponenten verwenden, um den Spielstatus / die Spielschnittstelle mit dem Benutzer zu aktualisieren.
  • Eine " Entität " ist im Grunde nur eine ID, mit der bestimmte Komponenten abgerufen und ihre Daten in der Spielelogik geändert werden.

Jedes System besitzt ein (ID-zugeordnetes) Array seines Komponententyps (z. B. Physik-> Physikkomponente, AI-> AIComponent, Rendering-> RenderingComponent), sodass es effizient über Daten iterieren kann.

Nicht alle Komponenten gehören jedoch speziell einem System. Eine Transformationskomponente speichert beispielsweise die Position, Drehung und Skalierung eines Objekts. Es ist einer der wichtigsten Teile einer Entität (Unity macht es sogar obligatorisch), da es von vielen Systemen verwendet wird, z. B. Physik, KI, Rendering usw.

Dies ist so ziemlich das Problem, mit dem ich konfrontiert bin. Wie kann ich vorgehen, da Transform von vielen anderen Systemen verwendet wird, um eines für jede Komponente zu finden? Eine mögliche Lösung besteht darin, dass jede Komponente ihre eigene Entitäts-ID speichert. Es wäre einfach, eine solche Komponente abzurufen, aber es wäre nicht so effizient, und es würde auch gegen das Konzept einer Komponente als isoliertes und unabhängiges Datenbündel verstoßen, das keine andere kennt.

Gibt es einen geeigneten Weg, um dieses Problem zu lösen? Sollte Transform überhaupt eine Komponente sein?


3
+1 für "Lassen Sie mich zunächst ein wenig Terminologie festlegen, die ich in dieser Frage verwenden werde:"
Vaillancourt

Ich würde diese Art von Fragen gerne mehr auf dieser Seite sehen. +1
S. Tarık Çetin

Speichern Sie einfach alle Komponenten als globale Variablen
Miles Rout

Antworten:


2

Dies ist eine ziemlich breite Frage, deren Antwort stark von Ihrer Architektur abhängt. Ich werde jedoch versuchen, Ihnen eine allgemeine Antwort zu geben.

Ihre Physik- und Rendering-Systeme erfordern sicherlich die Transformation, das KI-System jedoch nicht. Daher ist es sinnvoll, die Transformation in eine eigene Komponentenklasse zu kapseln. Alle derartigen interessierten Systeme würden dieselben Daten verwenden. Daher ist es sinnvoll, dass die Entität einen Zeiger auf das Transformationsobjekt oder eine ID für ein an anderer Stelle gespeichertes Transformationsobjekt hat.

Wenn Sie sich für die letztere Lösung entscheiden, benötigt jedes System, das an einer Transformation interessiert ist, Zugriff auf den Speicherort des Transformationsobjekts.

Wenn Sie die erstere auswählen, muss jedes System lediglich auf die Entität selbst zugreifen und die Transformation anfordern.

Im ersteren Fall besteht das Problem darin, wie Sie jedem System Zugriff auf den Speicher für Transformationen gewähren können, ohne die OOP-Regeln zu verletzen, wenn Sie sich für solche Dinge interessieren.

Der letztere Fall weist keine derartigen Probleme auf, erfordert jedoch das Ändern des Entitätsobjektdesigns, um Zeiger auf Objekte anstelle von IDs von Komponentenobjekten zu speichern.

Meine persönliche Präferenz ist das Entwerfen der Entitätsklasse zum Speichern von Zeigern auf Komponentenobjekte, da dies viele Entwurfsprobleme vereinfacht. Auf diese Weise kann jedes System, das eine Transformation benötigt, diese von der Entität anfordern und ignorieren, wenn dies nicht der Fall ist. Dies ist jedoch mit einem Rechenaufwand verbunden, der Zeigern inhärent ist, dh den Kosten für Cache-Fehlschläge.

Weitere Informationen hierzu finden Sie in dieser ECS-Übersicht .

Letztendlich liegt es an Ihnen, zu entscheiden, was für Sie wichtiger ist: einfache Entwicklung oder Leistung.

Abschließend möchte ich darauf hinweisen, dass Ihre Frage ein hervorragendes Beispiel für die Entwurfsfragen ist, über die ECS-Befürworter nachdenken, und dass es keine endgültige Silberkugel-Lösung gibt.


Vielen Dank für Ihre Vorschläge. Ich habe jedoch eine Frage: Warum braucht das KI-System nicht die Position eines Objekts?
CRefice

Sie verwechseln die Position (Vektor mit 3 Gleitkommazahlen) mit einer Translation (Transformationsmatrix, die aus einem Positionsvektor aufgebaut ist). Eine Transformationsmatrix besteht aus Translations-, Rotations- und Skalentransformationen. Dies sind weit mehr Informationen, als ein KI-System benötigen würde, obwohl Sie sicherlich den Positionsvektor daraus extrahieren könnten. Persönlich würde ich jedoch Position, Ausrichtung und Größen in ihre eigene Komponente aufteilen und sie zum Erstellen und Aktualisieren der Transformation verwenden.
Ian Young

@IanYoung Das Trennen kann mehr schaden als nützen, möglicherweise wenn Sie feststellen, dass Sie Position und Orientierung häufiger zusammen benötigen als Position oder Orientierung getrennt. In diesem Fall kann das Platzieren von Positions- und Orientierungsdatenattributen in einer einzelnen Komponente die Cache-Leistung verbessern.
Naros

1
Ich bevorzuge es, alle drei, Position, Ausrichtung und Skalierung in einer einzigen Komponente zu kombinieren. In Fällen, in denen ein bestimmtes Subsystem nur eine Position oder Ausrichtung benötigt, würde ich empfehlen, die Daten zu duplizieren und an klar definierten Punkten in der Spielschleife zu synchronisieren .
Naros

@Naros Ja, das habe ich gemeint: Zwei Komponenten, Transform und (in meinem Framework) SpatialData, die Position, Geschwindigkeit, Orientierung und Winkelgeschwindigkeit enthalten. Die Position und Ausrichtung werden verwendet, um die Transformation zu erstellen und zu aktualisieren.
Ian Young
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.