Conception basée sur les composants / entités + Arbres de comportement => comment intégrer?

9

Pour mon projet actuel, j'ai implémenté un système basé sur des composants / entités , suivant essentiellement la plupart des meilleures pratiques qui existent dans ce domaine plutôt indéfini .

J'ai donc obtenu des entités (légèrement étendues) , qui sont essentiellement un intID, un nom lisible par l'homme, un std::mapdes composants et un long"indicateur de type" qui est utilisé pour montrer quels composants sont présents (j'ai une puissance de deux enumpour tous les composants types et chaque fois qu'un composant est ajouté à l'entité, je modifie automatiquement cette longue via des opérations au niveau du bit, comparer cette réponse ).

Ensuite, il y a les composants , également assez simples: l' intID, enumcomme type de composant, le pointeur d'entité parent et une std::mapde toutes les propriétés de ce composant.

Enfin, certains systèmes / gestionnaires qui gèrent le traitement logique réel. Ils vérifient d'abord si l'entité actuellement traitée a un long"indicateur de type" correspondant = tous les composants nécessaires pour ce système sont présents. Il accède ensuite à certaines propriétés si nécessaire et appelle directement certaines fonctions dans le composant respectif ou envoie des messages (via un répartiteur de messages).

Conclusion: Jusqu'à présent, un système basé sur des composants / entités plutôt standard basé sur des événements combiné à une approche basée sur les données (comparer, les composants n'ont pas de variables de données codées en dur, mais plutôt une carte générique, comme (certains) composants / Les archétypes de composants seront ensuite lus à partir de fichiers avec la possibilité d'ajouter des données supplémentaires, qui ne font pas partie du code de composant réel.

Maintenant, je voudrais également introduire des arbres de comportement (basés sur AiGameDev BTSK ) dans ce projet, mais je ne sais pas si et comment ils doivent être liés aux composants déjà existants ou comment intégrer ces conceptions en général.

Plusieurs idées / points / questions connexes me viennent à l'esprit:

  1. Mes BT seront lus à partir de fichiers (à nouveau). J'ai actuellement du mal à voir comment je ferais au mieux la connexion entre un BT Actiondans cet arbre et le codage réel dans mon application. Dois-je créer une sorte de mappage entre les noms d'actions utilisés dans les fichiers BT et un pointeur de fonction vers l'implémentation logique réelle? Quelle est l'approche habituelle pour résoudre ce problème?

  2. Je suppose que je devrai créer des BT pour tous mes différents Entitytypes (donc pour chaque combinaison de composants de logique de jeu / IA, comme indiqué par mon long "indicateur de type" mentionné plusieurs fois). Par conséquent, il n'est pas logique de mettre les BT Actionimplémentations dans les composants, car de nombreux composants seront probablement impliqués par action, n'est-ce pas?

  3. La BT Actionlogique devrait-elle donc reposer sur un / plusieurs systèmes séparés (vers les méthodes desquelles la carte de l'idée n ° 1 pointe)? Le système vérifierait alors par mon long"indicateur de type" si le Entitypour lequel le BT est actuellement vérifié et qui a été invité à exécuter une certaine action (= méthode dans le système) est réellement autorisé à le faire (= a les composants nécessaires). Mais alors, sinon (parce que par exemple le créateur de BT a négligé une situation spécifique, où un composant nécessaire pourrait ne plus être attaché à l'entité au moment de l'exécution), rien ne se passerait.

Des questions:

  • Existe-t-il des concepts éprouvés pour ce type d'intégration?
  • Quelle est votre opinion sur mes 3 points ci-dessus?
  • Y a-t-il d'autres choses qui me viennent à l'esprit, concernant également ma conception basée sur les composants / entités en général?
Philip Allgaier
la source
Concernant le point 1: les arbres de comportement ne sont rien de plus qu'un DSL visuel utilisé principalement pour créer un comportement de personnage. Un composant BehaviorTree ne doit rien faire de plus ou de moins que ne le ferait un composant Script. Concernant le point 3: Quelle est la raison d'utiliser une carte sur des champs normaux?
Eric
# 1: Que signifie "DSL" dans ce contexte? # 3: Désolé, mais je ne peux pas vous suivre sur celui-ci. Voulez-vous expliquer ce que vous voulez dire?
Philip Allgaier
1
probablement un langage spécifique au domaine, c'est-à-dire. une syntaxe personnalisée pour travailler avec un problème très spécifique.
Patrick Hughes
Patrick a raison, même si une sémantique en fait également partie et "très" peut être supprimée de cette définition. - Re 3: Mes excuses, il devrait se lire: "Quelle est la raison d'utiliser une carte sur des champs réguliers dans les composants ?"
Eric
Re 3: Je veux pouvoir plus tard spécifier dynamiquement des propriétés supplémentaires en dehors du code C ++ (mot à la mode: piloté par les données). Par souci de simplicité, j'ai (au moins pour l'instant) mis toutes les propriétés dans ce cadre générique (en utilisant des cartes), même celles qui sont fixes dans le code et pourraient donc être de vrais champs C ++. Il faudra peut-être revoir cela plus tard, si cela devient un problème de performance ...
Philip Allgaier

Réponses:

2

J'ai actuellement du mal à voir comment je ferais au mieux la connexion entre une action BT dans cet arbre et le codage réel dans mon application. Dois-je créer une sorte de mappage entre les noms d'actions utilisés dans les fichiers BT et un pointeur de fonction vers l'implémentation logique réelle? Quelle est l'approche habituelle pour résoudre ce problème?

Oubliez les pointeurs de fonction et pensez aux objets. Chaque nœud de l'arbre de comportement (BT à partir de ce moment) correspondrait idéalement à un objet dans votre code. Ces objets auront une interface standard pour vous permettre de les organiser comme un arbre et de les parcourir. Un ensemble de pointeurs de fonction convient parfaitement au comportement, mais il ne capture pas du tout la structure de votre arbre.

Par conséquent, il n'est pas logique de mettre les implémentations BT Action dans les composants, car de nombreux composants seront probablement impliqués par action, n'est-ce pas?

Je m'attendrais à ce que les entités aient un seul composant BehaviorTree qui stocke les données pertinentes pour le BT de cette entité. L'exécution du BT est effectuée par le composant BT ou le sous-système BT, selon la façon dont vous gérez les composants de votre système. Comme avec à peu près tout ce qui utilise des composants, ils devront se référer à d'autres composants pour faire le travail, mais ces autres composants n'auront rien à savoir sur les BT.

Les différentes actions disponibles seraient, au niveau le plus simple, encodées dans les différents objets nœuds BT. Ils devraient être capables de faire agir l'entité concernée en manipulant les composants selon les besoins, par exemple. accéder au composant de mouvement pour se déplacer.

Kylotan
la source
Paragraphe # 1: Oui, le BT lui-même sera un objet (comme je l'ai dit comme la version d'AiGameDev). Je pensais juste aux foncteurs pour les actions elles-mêmes, mais votre paragraphe # 2 a changé cela. Pour une raison quelconque, cette approche vraiment simple ne m'est jamais venue à l'esprit (l'entité ayant sa propre instance de membre BT). Probablement en raison de la toute nouvelle composante, je ne pensais plus simplement et simplement, donc je cherchais un moyen de mélanger les composants avec les trucs BT, mais ce n'est pas vraiment nécessaire.
Philip Allgaier
La principale chose sur laquelle je me suis perdu auparavant était de savoir comment connecter l'action à l'entité. Maintenant, c'est clair: les actions savent à quelle entité via son arbre qui en retour connaît l'entité à laquelle il appartient.
Philip Allgaier
@Philip Allgaier Je suis curieux, comment avez-vous fini par créer le nœud BT? L'avez-vous créé en tant que nœud de comportement = 1 entité (ce qui représenterait beaucoup d'entités par 1 objet de jeu), ou avez-vous créé un nœud en tant que classe normale (non liée à ECS), ou avez-vous utilisé d'autres approches? Remercier!
cppBeginner