shared_ptr - Alternative?
-
Auch das sprach ich an.
Nexus schrieb:
Ein Kompromiss bestünde z.B. darin, die Komponenten zentral (nicht in den Entities) abzuspeichern, und dabei gleiche Komponententypen zusammenzufassen (in Containern von Containern à la
std::deque). Macht dann aber alles andere komplizierter, vor allem das Hinzufügen/Entfernen. Würde ich also wirklich erst tun, wenn die reine Iteration das Bottleneck wird. Und dazu müssen die Aktionen der Komponenten vergleichsweise billig sein.Vor allem aber löst es das Problem nicht. Wie würdest du
C& component = entity.getComponent<C>();implementieren? Diese Funktionalität brauchst du, wenn du von einer Komponente auf eine andere zugreifen willst (z.B. Movement benötigt Informationen über Pathfinding). Wie löst du Abhängigkeiten zwischen Komponenten auf?
Wenn du die Idee umkehrst, sodass Komponenten mehrere Entities enthalten und nicht umgekehrt, kannst du natürlich
componentContainer.find(entity)benutzen -- nur, wie kommst du von
CaufcomponentContainer?Wäre wirklich interessant, das zu klären. Wenn du generisch bleiben willst, musst du irgendwo Typ-IDs benutzen.
-
Voneinander abhängige Komponenten sollten wohl auch voneinander wissen. Sobald sie das tun, können sie über typspezifische Interfaces, welche nur den abhängigen Komponenten bekannt sein müssen, entsprechende Informationen austauschen (die Entity ID ist ja global bekannt). Sobald das Movement das Pathfinding kennt (muss ja nur bei der Initialisierung übergeben werden), kann dieses z.B. die Positionen jederzeit dort abfragen. Umgekehrt kann das Pathfinding jederzeit das Movement fragen, welche Bewegungen von einem konkreten Entity ausgeführt werden können etc. Soweit ich das sehe sollte sich das alles so auch in einem ansonsten dynamischen System völlig typsicher und ohne Downcast welcher Art auch immer umsetzen lassen...
-
Du lässt die Frage unbeantwortet, wie sich Movement und PathFinding überhaupt erst kennen lernen. Verdrahtest du etwa manuell Zeiger zwischen allen abhängigen Komponenten? Das ist unnötiger und fehleranfälliger Verwaltungsaufwand, der einfach automatisiert werden kann.
Ne, idealerweise sagt die Movement-Implementierung: "Gib mir einen Zeiger auf das PathFinding der gleichen Entity". Nach einem Mal kann man den immer noch cachen, um die Abfrage zu sparen. Der Punkt ist, dass du diese Information über eine Komponenten-Tabelle lösen musst, wenn du Hardcoding vermeiden willst -- eine Tabelle, deren Schlüssel Typ-IDs sind.
-
Nexus schrieb:
Du lässt die Frage unbeantwortet, wie sich Movement und PathFinding überhaupt erst kennen lernen. Verdrahtest du etwa manuell Zeiger zwischen allen abhängigen Komponenten? Das ist unnötiger und fehleranfälliger Verwaltungsaufwand, der einfach automatisiert werden kann.
Na dann automatisier es halt, sobald sie sich kennen, kennen sie sich; seh nicht, wo es da jetzt konkret scheitert...
Nexus schrieb:
Ne, idealerweise sagt die Movement-Implementierung: "Gib mir einen Zeiger auf das PathFinding der gleichen Entity". Nach einem Mal kann man den immer noch cachen, um die Abfrage zu sparen. Der Punkt ist, dass du diese Information über eine Komponenten-Tabelle lösen musst, wenn du Hardcoding vermeiden willst -- eine Tabelle, deren Schlüssel Typ-IDs sind.
Nun, ich würds nicht so lösen, da ich keinen Sinn darin sehe. Irgendwo muss festgelegt werden, genau welche Komponenten (in genau welcher Reihenfolge) geladen werden müssen. Und das wird wohl irgendwo ganz oben in der Anwendung passieren, da die Anwendung ohne zumindest ihre Kernkomponenten sowieso nicht funktioniert. Ergo würd ich den jeweiligen Komponenten, ganz im Sinne von Dependency Injection, bei der Instanzierung einfach Zeiger auf die entsprechenden anderen Komponenten übergeben oder ähnliches. Man kann es natürlich auch voll data driven machen oder was weiß ich, macht aber in 99% der Fälle vermutlich alles nur unnötig kompliziert...
-
Bei der Instanzierung fällt aus, weil das eine fixe Anzahl von typisierten Komponenten voraussetzen würde. Die Kernidee ist es aber doch, die Einschränkungen, die man durch eine fixe Anzahl von Komponententypen und Abhängigkeiten durch die gesamte Quellcodebasis ziehen würde, zu vermeiden.
Ob mann nun aber get<X>(entity) oder entity.get<X>() schreibt, ist ja ziemlich Rille, hinter den Vorhängen könnte beides auch ohne GetType ineinander übersetzt werden.
Man verliert ohne eine GetType-Version allerdings die Möglichkeit, die Verwaltung für Plugins umzusetzen, weil alle Komponententypen zur Compile-Zeit bekannt sein müssen.
Außerdem verliert man auch eine Menge Möglichkeiten im Zusammenhang mit Skripting und Serialisierung meinetwegen, wenn man nicht irgendwelche Typinformationen zur Verfügung hat.
type_index hat nicht die Skripting- und Serialisierungs-Problematik, allerdings ebenfalls die Probleme mit Plugins.