Spiele-Code-Design. Entity & Component Modell vs. irgendwas anderes

    Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

    • Spiele-Code-Design. Entity & Component Modell vs. irgendwas anderes

      Hi,

      dies hier ist mein erster Beitrag hier im Forum. Ich habe mich angemeldet um zu folgender Situation Feedback zu bekommen: (Ist eine rein logische Frage zur Code-Philosophie)

      Ich arbeite an der Code-Struktur für eine Spiele-Entwicklung und habe da momentan zwei Ansätze, beide auch schon im Code verwirklicht:

      Erster Ansatz: Hierarchischer Ansatz. Es gibt verschiedene Ebenen wie z.B. "Vordergrund", "Hintergrund", "Zwischeneben 1", ... Diese jeweiligen Ebenen haben dann einzelne Objekte wie z.B. auch die Spielfigur, Gegner, Hindernisse und so weiter. Die Hintergrundebenen kümmern sich dabei um die grafische Ausfüllung, z.B. durch sich automatisch erweiternde Bäume und andere grafische Spielereien. Die jeweiligen Ebenen sind dabei voneinander getrennt und müssen zur Laufzeit auch keine Daten austauschen. Die Logik für Gegner, Spieler und andere Sachen findet in den jeweiligen Objekten selbst statt. Das Erstellen von neuen Objekte zur Laufzeit ebenfalls. Ggf. noch in der Ebene unterhalb. Niemals aber an einem gemeinsamen Punkt z.B. in einer "Controller"-Klasse oder gleichen.

      Zweiter Ansatz: Component & Entity. Die Hierarchie beim Rendering ist die selbe. Jedoch gibt es eine "Master"-Klasse in der alle Entities, sprich Objekte wie Gegner, die Spielfigur, Hindernisse aber auch Ebenen, Kamera, etc. erzeugt werden und mit ihren jeweiligen Components, wie z.B. Rendering-Component, Scrolling-Component, Logic-Component, Kollisions-Component, etc. verbunden werden.

      Beide Ansätze funktionieren. Nur verbraucht der zweite Ansatz ein wenig mehr Ressourcen und benötigt erheblich mehr Code für das Component&Entity System. Persönlich gefällt mir der Component&Entity Ansatz, also der zweite Ansatz, sehr gut. Nur eine Sache stört mich gewaltig: Im Gegensatz zur dezentralen Variante des ersten Ansatzes habe ich nun wieder eine riesige Klasse die sich um die Erstellung und Verbindung der Entities mit den jeweiligen Components kümmert. Auch wenn dies später beim Laden von Level-Daten ggf. von Vorteil sein kann, ist es für mich jedoch zur Zeit irgendwie hässlich mit anzusehen. Ein Auslagern der Erstellung in die jeweiligen Entities habe ich auch schon in Erwägung gezogen. Nur dann muss ich zwischen den Klassen wieder jede Menge Referenzen hin und herschicken und bin somit wieder fasst bei meinem ersten Ansatz.

      Vielleicht habt ihr ja ähnliche Erfahrungen machen können? Was wäre euer Ansatz? Vielleicht habe ich das Entity&Component-Modell ja auch falsch verstanden!? Für welchen Ansatz würdet ihr euch entscheiden!?

      Vielen Dank,

      Simon
    • Hallo und herzlich Willkommen.

      Kennst du bereits die Sample App Demo Bots von Apple?
      Dort ist das Component Modell zusammen mit dem neuen GameKit Framework umgesetzt. In diesem Beispiel ist der Code das absolute Gegenteil von "one big class". Jedes bisschen, selbst die Status einer Waffe, sind dort eine eigene Klasse. Dadurch ist alles für meinen Geschmack stark fragmentiert. Oder anders gesagt: ich werde mit dem Component Modell nicht warm.

      Ich bin also ein Fan des "ersten" Ansatzes. Wobei aus meiner Sicht die einzelnen Ebenen nicht zwangsweise voneinander getrennt sein müssen. Für mich hat es sich bewährt eine übergeordnete Controller Klasse zu haben, welche die einzelnen Ebenen steuert. Anwendungsfälle sind hier zum Beispiel, das Aufrufen des Pause Menus. Wie stellst du ohne orchestrierende Instanz sicher, dass nicht z.B. weiter Gegner spawnen? Sicherlich kann man dies auch alles über Local Notifications lösen. Sehe ich aber kaum Mehrwert drin.

      Du hast nicht erwähnt, ob es mehrere Level gibt. Falls dem so ist, hat es sich für mich bewährt die Spiellogik in einer Klasse auszulagern. Die einzelnen Level erben dann von der Logik Klasse und ergänzen die Level-spezifischen Details.

      Schöne Grüße.

      PS: endlich ein Spieleentwickler im Forum.
    • Hallo iOSCampus und vielen Dank!

      Ja die Sample App kenne ich. Und einiges der da verwendeten Struktur ähnelt sehr meinem Ansatz. Was ich dort sehr gut finde ist unter Anderem die Ausklammerung der Kollisionsabfrage über eine gesonderte Handler-Klasse und die Weitergabe der Ereignisse über Protocol, etc. Das handhabe ich bei mir auch immer so.

      Einige Dinge halte ich jedoch bei genauerer Betrachtung für unnötig komplex, man muss aber bedenken, dass es eben ein "sample" zwecks Veranschaulichung ist. Aber die Theorie hinter den sog. Render-Components ist klar. Nur in der Sample-App bedeutet dies auch immer das ich zwischen den jeweiligen Sprites und dessen Mutter einen weiteren Drawing-Pass einbaue. Für meiner Meinung, wenn ein Sprite nicht aus vielen Sub-Sprites besteht, unnötige Ressourcenverschwendung. Aber wie schon gesagt, es ist ein "Sample" zwecks Veranschaulichung.

      Zu deiner Antwort: Ich habe den zweiten Ansatz ähnlich des DemoBot Samples adaptiert und habe nun folgendes - rein logisches - Problem - oder sagen wir, auch ich werde hier nicht wirklich "warm".

      Alle meine Objekte sind nun Entities und in diesem Falle auch eine Subklasse von GKEntity, der Entity-Klasse aus dem GameplayKit. Diese Objekte haben nun Components, ebenfalls Subklassen aber von der GKComponent-Klasse aus selbigem Framework. Viele dieser Components benötigen das Frame-weise Updating. Dies ist bereits im GameplayKit implementiert aber wird jedoch nur dann aufgerufen bzw. durchgeführt, wenn die jeweiligen Components sich innerhalb eines sog. GKComponentSystem befinden. Dann kommt noch hinzu, dass die Update-Routine dieser GKComponentSystem Instanz dann auch irgendwo aufgerufen werden muss. Hier bietet sich die Grund-Szene, eine SKScene, an, denn hier gibt es einen Update-Callback.

      Für das Erstellen von neuen Entities und der Verknüpfung mit jeweiligen Components - entweder zur Initialisierung oder eben auch zur Laufzeit - bedeutet das nun, dass alle GKComponent-Instanzen an einer zentralen Stelle gesammelt werden. Möchte ich nun aus einer Entity heraus eine Sub-Entity erstellen und verknüpfe diese dann mit Components, so muss ich entweder jede Menge Referenzen auf z.B. das Component-System mitschleppen, was ich aber Zwecks Spaghettiehrung des Codes nicht möchte - oder aber - Ich erstelle sämtliche Entities, Components und deren Verknüpfungen in einer Klassen, von der aus diese dann auch verwaltet werden. Also alles andere als dezentral. Und das ist mir noch etwas unschön.

      Alle Funktionen wie Kollisionsabfrage, Intelligenz, Steuerung, Scrolling, Camera, etc. sind als Component ausgelagert. Die Erstellung aller Objekte im Code jedoch finden an einer einzigen Stelle statt.

      Meine sonst übliche Vorgehensweise war es, die Erstellung auch in die jeweiligen Objekte zu übergeben. Ein Player z.B. der eine Schuss abfeuert, muss diesen Schuss auch selbst erstellen und nicht erst eine Übergeordneten Controller-Klasse per Protocol/Delegate oder anderem sagen, dass er schießen möchte und ob sich die Klasse bitte darum kümmern könnte.

      Tja. Es führen ja bekanntlich viele Wege nach Rom.

      Wie auch immer. Das Spiel wird Level haben, ja. Und sobald etwas mehr zu zeigen ist, werde ich das hier noch posten!

      Danke,

      Simon
    • Wir nutzen ein Entity Component System in unserer Engine. Die Gründe dafür sind das es modular und flexibel ist. Wir können schnell Änderungen durchführen und neue Ideen ausprobieren. Das System ist vom Editor aus steuerbar wodurch auch nicht Programmierer Änderungen durchführen können.

      Es gibt nicht nur die eine Methode solch ein System zu implementieren. Ich weiß von befreundeten Entwicklern das die Entity Component Systeme in kleinen Mobile Spielen bis hin zu Multimillionen Dollar Projekten für PCs und Konsolen nutzen.

      Wir haben uns am Anfang der Entwicklung diverse Umsetzungen solcher Systeme angesehen und dann die besten Ansätze genommen und mit unseren eigenen Anforderungen und Ideen gemischt. Unser Entity Component System nutzen wir mittlerweile projektübergreifend. Durch die Modularität lassen sich völlig verschiede Spiele umsetzen mit vergleichsweise wenig Code neuen Code. Wenn wir jetzt an ein Projekt gehen haben wir Code im Haus der schon erprobt ist und von dem wir wissen das der funktioniert.

      Die Performance war für uns kein Problem. Durch klare Regeln, diverse Optimierungen und Möglichkeiten den Update Loop besser zu kontrollieren dürfte die Performance sogar noch höher sein als bei vielen anderen Systemen bzw. Modellen. Es mag zwar vorkommen das der Code länger ist als er bei anderen Systemen wäre, das heißt aber nicht zwingend das der Code langsamer ist.

      Ganz kurz: Entity Component Systeme funktionieren, man muss nur Arbeit reinstecken sein eigenes Konzept zu entwickeln und keine Angst davor haben bestehende Dinge umzuwerfen.
    • Also ich habe letzte Nacht ein wenig mit dem Entity & Component System gearbeitet und ich muss sagen: I love it! Meine Probleme damit resultierten einzig aus dem Umbau meines ersten Ansatzes hin zum Entity Component Modell. Als ich dann allerdings damit begonnen habe, den Code auf Basis des E&C Modells weiterzuentwickeln, habe ich in der Praxis erlebt warum das Modell, wenn richtig implementiert, viele Vorteile bringen kann.