Ich habe mich schon seit einiger Zeit für das komponentenbasierte Entity-System interessiert und unzählige Artikel darüber gelesen (Die Insomiac-Spiele , der hübsche Standard Evolve Your Hierarchy , die T-Machine , Chronoclast ... um nur einige zu nennen).
Sie scheinen alle eine Struktur von außen zu haben, die etwa so aussieht:
Entity e = Entity.Create();
e.AddComponent(RenderComponent, ...);
//do lots of stuff
e.GetComponent<PositionComponent>(...).SetPos(4, 5, 6);
Und wenn Sie die Idee der gemeinsamen Nutzung von Daten einbringen (dies ist das beste Design, das ich bisher gesehen habe, um Daten nicht überall zu duplizieren).
e.GetProperty<string>("Name").Value = "blah";
Ja, das ist sehr effizient. Es ist jedoch nicht gerade am einfachsten zu lesen oder zu schreiben. es fühlt sich sehr klobig an und arbeitet gegen dich.
Ich persönlich würde gerne etwas machen wie:
e.SetPosition(4, 5, 6);
e.Name = "Blah";
Natürlich ist der einzige Weg, zu dieser Art von Design zu gelangen, zurück in der Entität-> NPC-> Feind-> Fliegender Feind-> Fliegender Feind mit einer Art Hierarchie, die dieses Design zu vermeiden versucht.
Hat jemand ein Design für diese Art von Komponentensystem gesehen, das immer noch flexibel ist und dennoch ein hohes Maß an Benutzerfreundlichkeit bietet? Und was das angeht, schafft man es, die (wahrscheinlich schwierigste) Datenspeicherung auf eine gute Art und Weise zu umgehen?
Welche Designs gibt es für ein komponentenbasiertes Entitätssystem, das benutzerfreundlich und dennoch flexibel ist?
quelle
Ich würde vorschlagen, eine Art Interface-Klasse für Ihre Entity-Objekte wäre schön. Es könnte die Fehlerbehandlung mit der Überprüfung durchführen, um sicherzustellen, dass eine Entität auch eine Komponente des entsprechenden Werts an einem Ort enthält, sodass Sie dies nicht überall tun müssen, wo Sie auf die Werte zugreifen. Alternativ beschäftige ich mich bei den meisten Entwürfen, die ich jemals mit einem komponentenbasierten System durchgeführt habe, direkt mit den Komponenten, fordere beispielsweise deren Positionskomponente an und greife dann direkt auf die Eigenschaften dieser Komponente zu bzw. aktualisiere sie.
Auf hoher Ebene sehr einfach, nimmt die Klasse die betreffende Entität auf und bietet eine benutzerfreundliche Schnittstelle zu den zugrunde liegenden Komponententeilen wie folgt:
quelle
In Python können Sie den Teil 'setPosition' abfangen,
e.SetPosition(4,5,6)
indem Sie eine__getattr__
Funktion für Entity deklarieren . Diese Funktion kann die Komponenten durchlaufen und die entsprechende Methode oder Eigenschaft finden und diese zurückgeben, sodass der Funktionsaufruf oder die Funktionszuweisung an die richtige Stelle gelangt. Vielleicht hat C # ein ähnliches System, aber es ist möglicherweise nicht möglich, weil es statisch typisiert ist - es kann vermutlich nicht kompiliert werden,e.setPosition
wenn e nicht irgendwo setPosition in der Schnittstelle hat.Möglicherweise können Sie auch alle Entitäten veranlassen, die relevanten Schnittstellen für alle Komponenten zu implementieren, die Sie ihnen hinzufügen, und zwar mit Stub-Methoden, die eine Ausnahme auslösen. Wenn Sie dann addComponent aufrufen, leiten Sie einfach die Funktionen der Entität für die Schnittstelle dieser Komponente zur Komponente um. Ein bisschen fummelig.
Am einfachsten ist es jedoch, den Operator [] in Ihrer Entity-Klasse zu überladen, um die angehängten Komponenten auf das Vorhandensein einer gültigen Eigenschaft zu durchsuchen und diese zurückzugeben
e["Name"] = "blah"
. Jede Komponente muss ihr eigenes GetPropertyByName-Objekt implementieren, und die Entität ruft jedes einzeln auf, bis sie die Komponente findet, die für die betreffende Eigenschaft verantwortlich ist.quelle
GetProperty
Methode .. Einziger Nachteil ist die String-Manipulation und der Vergleich. Aber das ist ein strittiger Punkt.Um die Antwort von Kylotan zu erweitern, können Sie bei Verwendung von C # 4.0 statisch eine Variable eingeben, die dynamisch sein soll .
Wenn Sie von System.Dynamic.DynamicObject erben, können Sie TryGetMember und TrySetMember (unter den vielen virtuellen Methoden) überschreiben, um Komponentennamen abzufangen und die angeforderte Komponente zurückzugeben.
Ich habe über die Jahre ein bisschen über Entity-Systeme geschrieben, aber ich gehe davon aus, dass ich nicht mit den Giganten mithalten kann. Einige ES-Notizen (etwas veraltet und spiegeln nicht unbedingt mein aktuelles Verständnis von Entitätssystemen wider, aber es ist eine Lektüre wert, imho).
quelle
object
Parameter hat - aber all dies wird zur Laufzeit aufgelöst. Ich denke, es ist eine verherrlichte Möglichkeit, eine flüssige Schnittstelle über zB entity.TryGetComponent (compName, out component) zu halten. Ich bin nicht sicher, ob ich die Frage verstanden habe :)Ich sehe hier viel Interesse an ES auf C #. Schauen Sie sich meinen Port der exzellenten ES-Implementierung von Artemis an:
https://github.com/thelinuxlich/artemis_CSharp
Ein Beispielspiel, mit dem Sie beginnen können, wie es funktioniert (mit XNA 4): https://github.com/thelinuxlich/starwarrior_CSharp
Vorschläge sind willkommen!
quelle
Ich habe mich für das exzellente Reflexionssystem von C # entschieden. Ich habe es aus dem allgemeinen Komponentensystem und einer Mischung der Antworten hier abgeleitet.
Komponenten werden sehr einfach hinzugefügt:
Und kann entweder nach Name, Typ oder (falls üblich, nach Zustand und Position) nach Eigenschaften abgefragt werden:
Und entfernt:
Auf Daten wird häufig über Eigenschaften zugegriffen:
Welches ist komponentenseitig gespeichert; weniger Overhead, wenn es keine HP hat:
Die große Menge des Tippens wird von Intellisense in VS unterstützt, aber zum größten Teil gibt es wenig Tippen - das, wonach ich gesucht habe.
Hinter den Kulissen speichere ich eine
Dictionary<Type, Component>
und habeComponents
dieToString
Methode zur Namensüberprüfung außer Kraft gesetzt . Mein ursprünglicher Entwurf verwendete hauptsächlich Zeichenketten für Namen und Dinge, aber es wurde zu einem Schwein, mit dem man arbeiten konnte (oh schau, ich muss auch überall die fehlenden leicht zugänglichen Eigenschaften besetzen).quelle