Comme toujours, l'architecture dépend de vos besoins. Combien de foules allez-vous avoir? Quelle est la complexité de leur IA? À quoi réagit-il? À quelle fréquence change-t-il son état? Répondez à ces questions et vous comprendrez beaucoup mieux ce que vous voulez et comment l'obtenir.
En général, vous voudriez avoir au moins une sorte de système d'événements. L'IA est généralement définie en termes d'événements: "Quand A se produit, faites B"; et si vous n'avez pas d'événements dans le code réel, vous devrez en quelque sorte traduire ces définitions.
D'après mon expérience, vous pouvez vous en sortir avec une implémentation de boucle simple lorsque vous avez peu de mobs vraiment simples (contrairement à ce que l'autre réponse semble suggérer). Par exemple, dans notre jeu actuel, nous avons des centaines de petites instances avec chacune 10 mobs au maximum. Et ces foules sont complètement stupides; Une IA de 99% d'entre eux peut être décrite en une phrase: "Suis-je en train d'attaquer quelqu'un? Sinon, attaquez le joueur le plus proche." Dans ce cas, une simple boucle est plus que suffisante - deux fois par seconde, nous recherchons une nouvelle cible (et quelques autres choses pour les rares mobs "intelligents"), et cela le fait.
Cependant, lorsque vous avez des mobs plus nombreux et / ou plus intelligents, l'approche naïve cesse de fonctionner. Pour que l'IA réagisse à certains stimulus, vous devez écrire du code qui le détecte dans votre boucle d'IA. Par exemple: supposez que votre mob doive faire quelque chose "quand il est touché par un joueur". Avec une approche en boucle, il n'y a pas de moyen facile de déterminer si la foule a été touchée. Lorsque l'IA fonctionne, vous pouvez vérifier que la santé de la foule a diminué depuis le dernier tick ou que la foule est actuellement ciblée par quelqu'un. Mais vous ne pouvez pas détecter les hits réels sans recourir à des hacks, comme enregistrer chaque information de hit quelque part pour que l'IA y accède plus tard.
Deuxièmement, une boucle naïve s'exécute toujours, quoi qu'il arrive. Lorsque vous avez beaucoup de mobs, vous voulez que l'IA fonctionne aussi vite que possible .. et le code le plus rapide est le code qui ne s'exécute jamais du tout. Si vous avez des mobs qui ne sont pas actifs, vous voulez qu'ils n'exécutent pas l'intelligence artificielle, ou ne l'exécutent que sporadiquement (comme dans, l'intelligence artificielle errante ne doit s'exécuter que lorsqu'elle décide où aller ensuite).
Avec une approche basée sur les événements, vous pouvez demander à d’autres sous-systèmes d’envoyer des événements d’IA à tout moment, ce qui élimine le problème de «détection des hits». Bien sûr, certains événements nécessiteraient toujours la détection de code: l'exemple le plus notoire est l'événement "approche". Et lorsque vous n'exécutez pas votre routine d'IA en boucle lorsque rien ne se passe, vous gagnez en performances.
Vous pouvez également utiliser une approche hybride. Au lieu de gérer immédiatement les événements de l'IA, vous pouvez les placer dans une sorte de file d'attente. Ensuite, lorsque la routine AI s'exécute (en boucle), elle supprime les événements de cette file d'attente et les gère un par un. Avec cette architecture, les performances de l'IA peuvent être un peu plus lentes, mais elles sont plus prévisibles; vous pouvez également garantir que toute l'intelligence artificielle s'exécute sur un seul thread (ce qui pourrait être difficile autrement). Ce type de boucle peut également être facilement limité en sautant certains événements (par exemple, chaque itération AI ne gère que les trois événements les plus récents, en ignorant le reste). Ou les événements peuvent être classés par ordre de priorité et les événements moins importants rejetés si l'IA est en retard.
Dans l'ensemble, l'approche "boucle avec file d'attente d'événements" est probablement la plus flexible. Mais je tiens à répéter: ne choisissez pas simplement aveuglément comme "le meilleur". Pensez d'abord à vos besoins et une approche plus simple pourrait s'avérer meilleure.