Partikel / Instanzgruppen in einem Entitäts- / Komponentensystem

7

Ich habe kürzlich mit einem Entity / Component / System-Design gespielt und bin auf ein paar Stolpersteine ​​gestoßen.

Instanz

Nehmen wir an, ich habe ein paar hundert "Dinge" (Asteroiden, Hühner, was auch immer), die mit Instanzen gezeichnet werden. In einer klassischen Komponentenhierarchie hätte ich ein Spielobjekt, das den einzelnen Instanzindex und die Scheitelpunktpuffer sowie den zweiten dynamischen Scheitelpunktpuffer für die Instanzdaten (Sammlung von Matrizen usw.) enthält. Dieses Objekt ist für die Überprüfung von Kollisionen mit anderen Objekten und zwischen den Instanzen selbst verantwortlich.

In einem ES-System möchte ich jede Instanz als einzelne Entität verfolgen, aber ich möchte nicht auf die Einfachheit und Leistung der Instanzierung verzichten. Das erste, was mir einfiel, war das Erstellen einer "Instanzgruppen" -Komponente mit einem Feld, das eine Gruppen-ID definiert, um die Behandlung mehrerer Arten von instanziierter Geometrie zu ermöglichen.

Ein "Instanzsystem" würde diese Komponenten sammeln und den Instanzscheitelpunktpuffer verwalten. Mein Entitätsmanager benachrichtigt Systeme bereits, wenn eine Entität erstellt oder zerstört wird, was die Implementierung dieses Teils ziemlich einfach macht.

Meine Verwirrung kommt davon, wie man das sauber in das Rendering-System integriert. Wenn jede Instanz als separate Entität mit einer "renderbaren" Komponente / einem "renderbaren" Attribut angezeigt wird, werden sie vom Render-System einzeln verarbeitet.

Ich könnte:

  1. Fügen Sie einen Sonderfall für Entitäten hinzu, die sowohl eine "renderbare" als auch eine "instanziierte" Komponente haben, die jedoch chaotisch erscheint und den Weg eines riesigen Render-Systems mit Tonnen von Sonderfällen beschreitet.

  2. Lassen Sie das Render-System eine Sammlung von Instanz-Vertex-Puffern verwalten, die Entitätsliste nach "instanziierten" Entitäten abfragen, anhand einer Gruppen-ID filtern usw. und das entsprechende Rendern durchführen, damit das Render-System für die Verwaltung der Instanz-Sammlungen verantwortlich wird scheint der falsche Ort zu sein, um diese Art von Logik zu formulieren.

  3. Ich könnte auch eine einzelne Entität zusätzlich zu den Instanzen mit beispielsweise einer "InstanceOutput" -Komponente / einem "InstanceOutput" -Attribut und einer RenderableKomponente einfügen und die RenderableKomponente aus den einzelnen Instanzentitäten entfernen und einen einzelnen Renderpunkt für alle Instanzen angeben. Diese Komponente würde wahrscheinlich auch als Server dienen, um die Geometrie und den persistenten Instanz- / Vertex-Puffer beizubehalten.

Gibt es einen besseren Weg?

Rendern

Ich habe verschiedene Arten von renderbaren Entitäten. Einige haben prozedurale Geometrie und Texturen, andere sind nur Sprites, andere sind Textanzeigen. Was ist der beste Weg, um diese aus Sicht des Renderingsystems zu unterscheiden, ohne eine massive switchAussage schreiben zu müssen ? In einer Spielobjekthierarchie hätte jeder dieser Typen seine eigene Draw()Methode, aber das Verschieben der Logik in ein Render-System scheint nicht viel Flexibilität hinsichtlich verschiedener Effektparameter usw. zu bieten.

3Dave
quelle

Antworten:

5

Sie sind zu verallgemeinern und versuchen zu sehr, Ihre Vorstellung von einem Entitätssystem zu verwenden.

Die Instanzierung ist genauso einfach wie das automatische Stapeln aller renderbaren Objekte mit demselben Netz und denselben Materialien durch Ihren Renderer.

Es ist nicht die Aufgabe der Daten oder der Komponenten, sich selbst zu rendern. Es ist die Aufgabe des Renderingsystems, von dem erwartet werden sollte, dass es intelligent ist.

Es gibt auch keinen Grund, für jeden Renderertyp unzählige verschiedene Rendering-Systeme zu haben. Der Unterschied zwischen einem Sprite, einem Mesh und statischem Terrain beruht auf Materialien (unterschiedlicher Vertex-Shader für Sprit-Boarding-Sprites über Beleuchtungsnetze) und Zeichnungsreihenfolge, die alle vollständig von demselben System und sogar von genau demselben Render verarbeitet werden können Pipeline.

Sean Middleditch
quelle
Ich mag diese Idee. Lassen Sie den Renderer jede Entität, wie sie erstellt wurde, untersuchen und feststellen, ob sie mit ähnlichen Elementen gestapelt werden kann / sollte, anstatt auch nur das Rendering-System zu kennen oder zu instanziieren. Dies führt möglicherweise zu einer gewissen Komplexität, da sowohl eine instanziierende als auch eine nicht instanziierende Version der relevanten Shader vorhanden ist, und macht den Renderer für die Wartung der Puffer verantwortlich. Hmm.
3Dave
1
Der Renderer sollte für solche Dinge verantwortlich sein. Auch hier ist das komponentenbasierte Design ein großartiges Werkzeug, aber Sie können eine (vernünftige) Engine nicht vollständig auf einem Designmuster aufbauen. Erwarten Sie insbesondere bei Spielen und Grafiken einmalige Spezialsysteme. Und wenn Sie zum Gameplay kommen, erwarten Sie Haxx. :)
Sean Middleditch
Danke für die Tipps. Spezialisierter Code für die Behandlung von Randfällen scheint unvermeidlich, aber ich versuche, ihn eher zur Ausnahme als zur Regel zu machen. Andererseits ist dies keine Webentwicklung. Gott sei Dank.
3Dave
@seanmiddleditch Ich beginne zu entdecken, dass Randfälle, Hacks und einmalige Spezialteile eigentlich das Spiel selbst sind. Es ist völlig anders als bei Geschäftsanwendungen, bei denen sterile, starre Frameworks entworfen werden können :)
Piku
5

Ich denke, Sie verlieren möglicherweise einen Teil der Leistung der Instanz, wenn Sie jede Instanz zu einer Entität machen. Ich denke, Ihre Idee, eine Instanzgruppe zu verwenden, ist gut. Ich würde dann ein System erstellen, das nach Entitäten mit einer Instanzgruppenkomponente sucht und die Instanzen rendert. Wie andere Systeme kümmert sich dieses System nicht um andere Komponenten der Entität, einschließlich Renderable. Wenn die Entität auch eine renderbare Komponente hätte, die vom entsprechenden System aufgenommen und gerendert würde, aber das Rendern wäre nicht von den Instanzen. Wenn Sie beispielsweise einen Hühnergenerator hätten, würde das Instanzgruppensystem alle Hühner rendern und das renderbare System würde den Hühnergenerator rendern. Sie können ein separates System haben, das die Instanzen innerhalb der Instanzgruppenkomponenten aktualisiert.

Wie für andere Rendering-Sachen. Es wäre einfach, eine spriteRenderKomponente, eine textRenderKomponente oder eine andere Art von Komponente für jede unterschiedliche Art von Rendering zu erstellen . Dann haben Sie ein System für jede Komponente mit einem anderen Rendering-Stil. Zum Beispiel hat mein Spiel ein Billboard-Rendering-System, ein statisches Modell-Rendering-System und ein animiertes Modell-Rendering-System. Eine Entität kann alle oder eine beliebige Kombination haben. Zum Beispiel könnte ein Kobold eine animierte Modellkomponente für seinen Körper und eine Werbetafelkomponente für ein Statussymbol über seinem Kopf haben.

MichaelHouse
quelle
Das Problem, wenn nicht jedes "Huhn" eine Einheit ist, ist, dass sie dann nicht einfach von den anderen Systemen wie dem Eingabeprozessor, Bewegung / Animation, Kollisionserkennung usw.
manipuliert werden
Die Instanzgruppenkomponente kann alle erforderlichen Aktualisierungen empfangen und auf die Instanzen anwenden. Das Instanzgruppen-Aktualisierungssystem wäre für die Verarbeitung der Instanzgruppen verantwortlich.
MichaelHouse
Ich bin verwirrt, wie das funktionieren würde, wenn man beispielsweise ein Huhn mit einer nicht instanziierten Entität kollidiert. Wenn die Instanzen keine Entitäten sind und ihr gesamtes Verhalten von hühnerspezifischen Systemen verarbeitet wird, können sie nicht mit Entitäten interagieren, die nicht instanziiert sind oder nicht zur selben Gruppe gehören, ohne die Logik dieser anderen zu ändern Systeme, die den großen Nutzen von ECS zunichte machen. Was vermisse ich?
3Dave
Das System, das die Instanzgruppe verwaltet, ist der Interaktionspunkt für alle von ihm verwalteten Instanzen. Zum Beispiel hat Entität A eine Instanzkomponente, Entität B nicht. Wenn wir die Kollision zwischen A und B überprüfen, überprüfen wir auch alle Instanzen von A. Der "Physikkörper" von A enthält alle Instanzen. Wenn ein Huhn mit einer nicht instanziierten Entität kollidiert, ist dies eine Kollision mit dem Hühnergenerator. Das Instanzgruppensystem behandelt die Kollision.
MichaelHouse
Ist es komisch, dass ich "Chicken Pong" schreiben möchte?
3Dave