Je commence à implémenter l'IA du joueur et de l'ennemi dans un jeu, mais je ne sais pas comment l'implémenter au mieux dans une architecture de jeu basée sur les composants.
Disons que j'ai un personnage de joueur suivant qui peut être stationnaire, courir et balancer une épée. Un joueur peut passer à l'état d'épée pivotante à la fois à partir de l'état stationnaire et en cours d'exécution, mais ensuite le swing doit être terminé avant qu'il ne puisse reprendre la position debout ou courir. Pendant le swing, le joueur ne peut pas se déplacer.
Selon moi, j'ai deux approches de mise en œuvre:
- Créez un seul composant AI contenant toute la logique du joueur (soit découplé du composant réel, soit incorporé en tant que PlayerAIComponent). Je peux facilement appliquer les restrictions d'état sans créer de couplage entre les composants individuels composant l'entité du joueur. Cependant, le composant AI ne peut pas être décomposé. Si j'ai, par exemple, un ennemi qui ne peut que se tenir debout et marcher ou se promener et parfois balancer une épée, je dois créer de nouveaux composants d'IA.
- Décomposez le comportement en composants, chacun identifiant un état spécifique. J'obtiens alors un StandComponent, WalkComponent et SwingComponent. Pour appliquer les règles de transition, je dois coupler chaque composant. SwingComponent doit désactiver StandComponent et WalkComponent pendant la durée du swing. Lorsque j'ai un ennemi qui ne fait que rester debout, balançant une épée de temps en temps, je dois m'assurer que SwingComponent ne désactive WalkComponent que s'il est présent. Bien que cela permette de meilleurs mélanges et correspondances, cela peut conduire à un cauchemar de maintenabilité car chaque fois qu'une dépendance est ajoutée, les composants existants doivent être mis à jour pour bien jouer avec les nouvelles exigences que la dépendance impose au personnage.
La situation idéale serait qu'un concepteur puisse construire de nouveaux ennemis / joueurs en faisant glisser des composants dans un conteneur, sans avoir à toucher une seule ligne de moteur ou de code de script. Bien que je ne sois pas sûr que le codage de script puisse être évité, je veux le garder aussi simple que possible.
Pour résumer le tout: dois-je lober toute la logique de l'IA en un seul composant ou décomposer chaque état logique en composants séparés pour créer plus facilement des variantes d'entité?
edit : Je soupçonne qu'il y a une certaine confusion sur ce que je voulais dire avec la première et la deuxième situation. J'ai essayé de l'expliquer dans le diagramme ci-dessous.
Notez la relation entre les états individuels et l'entité. Dans la première situation, un composant AI est pré-construit avant d'être mis dans l'entité. Un concepteur peut uniquement choisir parmi un ensemble distinct de composants AIC mis à disposition par le programmeur. La deuxième situation a les différents états au même niveau que les autres composants. Un concepteur peut désormais créer une entité avec une IA unique sans interférence d'un programmeur.
La question est, sont-ce les deux seules options pour structurer l'IA dans une entité basée sur des composants et, si oui, qu'est-ce qui donnerait la flexibilité maximale?
la source
Réponses:
Si vous avez l'intention d'avoir plus d'ennemis ou de joueurs possibles que vous ne pouvez pas imaginer en ce moment, alors vous devez absolument le casser. Ce que vous décrivez dans votre deuxième point est essentiellement le modèle d'état .
Je pense que je suis d'accord avec Gregory sur le fait que vous ne devriez pas avoir de composants d'état de marche et de stand séparés. C'est juste un composant de mouvement avec la vitesse 0. D'un autre côté, si vous avez des objets qui ne peuvent pas bouger, vous devez soit le diviser, soit simplement mettre une sorte de restriction booléenne dans l'état de mouvement qui empêche d'avoir une vitesse non nulle .
Pour le joueur, je ne pense pas que cela doive être complètement séparé. Il peut toujours utiliser tous les autres composants, avec l'ajout d'un composant d'entrée. Ce composant pilote les transitions entre les états, tandis que chez l'ennemi, il est contrôlé par une IA par défaut, ou si vous le souhaitez, différentes sous-classes d'IA parmi lesquelles vos concepteurs ennemis peuvent choisir.
modifier: en fait, pour vos ennemis stationnaires, plutôt que de restreindre le composant de mouvement, donnez-leur simplement un composant IA stationnaire qui ne choisit jamais de les déplacer.
la source
Je garderais au moins Player AI (ou ce que j'appellerais Player Controller) comme son propre composant. Avec la plupart des jeux, le joueur est suffisamment différent des PNJ que vous ne pouvez pas généraliser de l'un à l'autre, sauf dans les bases comme les points de vie.
Pour les PNJ, je considère StandComponent et WalkComponent comme des aspects de la même chose. Allez-vous jamais avoir un WalkComponent sans StandComponent? J'en doute. De même, un RunComponent ne serait qu'un WalkComponent avec une vitesse plus élevée et des animations différentes. Je peux voir l'intérêt d'avoir un NPCMovementComponent et un NPCSwordFighterComponent séparé, mais même cela me semble être une ingénierie excessive.
la source
D'abord, je créerais un composant d'état, puis je créerais une machine d'état pour gérer les transitions. Rendez-le suffisamment générique pour pouvoir l'utiliser pour vos joueurs et votre IA. Cela garantira que l'IA joue selon les mêmes règles et que vous n'avez pas à changer votre logique lorsque vous modifiez le fonctionnement des états du joueur par rapport aux états de l'IA.
Machine à états finis C ++
Ce qui précède a un exemple concret d'une machine d'état en c ++ qui peut être utilisée par les joueurs et l'IA.
la source
Ce que vous voulez, c'est un composant gérant le mouvement des personnages (joueur et PNJ). Le composant AI ou un composant joueur enverra des commandes à ce composant de mouvement et il vérifiera si l'action peut être lancée. Cela encapsulera vos contraintes de mouvement en un seul composant. Votre code AI et votre code joueur n'ont pas besoin de savoir comment l'épée swing est exécutée. L'IA aurait des états internes, par exemple inactif, attaquant, fuyant.
la source