Für mein aktuelles Projekt habe ich ein komponenten- / entitätsbasiertes System implementiert , das im Wesentlichen den meisten Best Practices in diesem eher undefinierten Bereich folgt .
Also habe ich (leicht erweiterte) Entitäten erhalten , die im Grunde eine int
ID, einen für Menschen lesbaren Namen, eine std::map
der Komponenten und einen long
"Typindikator" sind, der verwendet wird, um anzuzeigen, welche Komponenten vorhanden sind (ich habe eine Zweierpotenz enum
für alle Komponenten Typen und wann immer eine Komponente zur Entität hinzugefügt wird, ändere ich diese Länge automatisch über bitweise Operationen (vergleiche diese Antwort ).
Dann gibt es die Komponenten , auch ziemlich einfach: int
ID enum
als Komponententyp, übergeordneter Entitätszeiger und eine std::map
aller Eigenschaften, die diese Komponente enthält.
Zuletzt einige Systeme / Manager , die die eigentliche Logikverarbeitung übernehmen. Sie prüfen zunächst, ob die aktuell verarbeitete Entität einen übereinstimmenden long
"Typindikator" hat = alle für dieses System erforderlichen Komponenten sind vorhanden. Bei Bedarf greift es dann auf einige Eigenschaften zu und ruft entweder einige Funktionen in der jeweiligen Komponente direkt auf oder sendet einige Nachrichten (über einen Nachrichten-Dispatcher).
Fazit: Bis hier ein eher standardmäßiges ereignisgesteuertes komponenten- / entitätsbasiertes System in Kombination mit einem datengesteuerten Ansatz (vergleiche, Komponenten haben keine fest codierten Datenvariablen, sondern eine generische Zuordnung als (einige) Komponenten / Archetypen von Komponenten werden später aus Dateien mit der Option gelesen, zusätzliche Daten hinzuzufügen, die nicht Teil des eigentlichen Komponentencodes sind.
Jetzt möchte ich auch Verhaltensbäume (basierend auf AiGameDev BTSK ) in dieses Projekt einführen , bin mir aber nicht sicher, ob und wie sie mit den bereits vorhandenen Komponenten verknüpft werden sollen oder wie diese Designs im Allgemeinen integriert werden sollen.
Einige verwandte Ideen / Punkte / Fragen kommen in den Sinn:
Meine BTs werden (wieder) aus Dateien gelesen. Es fällt mir derzeit schwer zu sehen, wie ich die Verbindung zwischen einem
BT Action
in diesem Baum und der tatsächlichen Codierung in meiner Anwendung am besten herstellen kann . Sollte ich eine Art Map zwischen den in den BT-Dateien verwendeten Aktionsnamen und einem Funktionszeiger auf die tatsächliche Logikimplementierung erstellen? Was ist der übliche Ansatz, um das zu lösen?Ich gehe davon aus, dass ich BTs für alle meine verschiedenen
Entity
Typen erstellen muss (also für jede spiellogik- / AI-relevante Kombination von Komponenten, wie durch meinen mehrfach erwähnten langen "Typindikator" angezeigt). Infolgedessen ist es nicht sinnvoll, dieBT Action
Implementierungen in die Komponenten einzufügen, da höchstwahrscheinlich viele Komponenten pro Aktion beteiligt sind, oder?Sollte sich die
BT Action
Logik also in einem / mehreren separaten Systemen befinden (auf deren Methoden die Karte von Idee Nr. 1 zeigt)? Das System würde dann anhand meineslong
"Typindikators" prüfen, ob das,Entity
für das das BT derzeit geprüft wird und das angewiesen wurde, eine bestimmte Aktion auszuführen (= Methode im System), dies tatsächlich darf (= die erforderlichen Komponenten hat). Andernfalls würde nichts passieren, da beispielsweise der BT-Ersteller eine bestimmte Situation übersehen hat, in der eine erforderliche Komponente zur Laufzeit möglicherweise nicht mehr an die Entität angehängt ist.
Fragen:
- Gibt es bewährte Konzepte für diese Art der Integration?
- Wie sehen Sie meine 3 Punkte oben?
- Gibt es noch andere Dinge, die mir in den Sinn kommen, auch in Bezug auf mein komponenten- / entitätsbasiertes Design im Allgemeinen?
quelle
Antworten:
Vergessen Sie Funktionszeiger und denken Sie an Objekte. Jeder Knoten im Verhaltensbaum (BT ab diesem Zeitpunkt) würde idealerweise einem Objekt in Ihrem Code entsprechen. Diese Objekte verfügen über eine Standardschnittstelle, über die Sie sie als Baum anordnen und durchlaufen können. Eine Reihe von Funktionszeigern ist für das Verhalten in Ordnung, erfasst jedoch überhaupt nicht die Struktur Ihres Baums.
Ich würde erwarten, dass Entitäten eine einzige BehaviorTree-Komponente haben, in der die relevanten Daten für das BT dieser Entität gespeichert sind. Die Ausführung des BT erfolgt entweder durch die BT-Komponente oder das BT-Subsystem, je nachdem, wie Sie mit Komponenten in Ihrem System umgehen. Wie bei so ziemlich allem, was Komponenten verwendet, müssen sie sich auf andere Komponenten beziehen, um die Arbeit zu erledigen, aber diese anderen Komponenten müssen nichts über BTs wissen.
Die verschiedenen verfügbaren Aktionen würden auf der einfachsten Ebene in die verschiedenen BT-Knotenobjekte codiert. Sie sollten in der Lage sein, die relevante Entität zum Handeln zu bewegen, indem sie die Komponenten nach Bedarf manipulieren, z. Zugriff auf die Bewegungskomponente zum Bewegen.
quelle