Comment gérer tous les objets NPC / AI sur le serveur?

8

J'écris un MMO simple et j'ai actuellement l'architecture serveur-client en place pour que plusieurs utilisateurs puissent se voir et pouvoir se déplacer ensemble ... il est maintenant temps d'ajouter des ennemis.

Je me demandais si quelqu'un avait des liens vers des articles qui discutaient de la meilleure façon de gérer les centaines d'objets PNJ qui doivent être gérés dans le monde. J'ai fait quelques recherches et je n'ai pas trouvé beaucoup d'informations sur la façon dont cela se fait généralement.

Les deux méthodes de structuration de l'implémentation auxquelles je pense:

  1. Tenir tous les objets NPC instanciés dans une liste, et avoir une boucle NPC Thread à travers eux séquentiellement et voir si chacun a une logique qui doit être traitée et effectuer les actions nécessaires. Je ne sais pas si les performances de cette conception seraient suffisantes?
  2. Système basé sur les événements. Créez une méthode dans la classe NPC qui traite AI / Logic dessus, demandez à cette méthode d'être appelée lorsqu'un événement associé est signalé, soit sur une minuterie pour une fonctionnalité AI non interagie (comme l'errance), soit signalez l'événement en externe à partir du paquet gestionnaire (joueur se déplaçant à proximité ou joueur attaquant à portée).

L'une ou l'autre de ces approches est-elle la bonne? Quelles autres méthodes existent pour ce faire?

dgo
la source

Réponses:

5

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.

Ça ne fait rien
la source
et juste pour compléter cette réponse, vous pouvez toujours ajouter des mobs ou les supprimer de votre boucle de vérification. par exemple. quand il n'y a personne pour observer ce que fait une foule, ce n'est tout simplement pas logique de faire tout ce que le PNJ ferait à ce moment-là. vous pouvez donc filtrer facilement de nombreux mobs et vérifier simplement si les plus importants (généralement ceux assez proches des joueurs) ont besoin de mises à jour
Ali1S232
Une «foule» est-elle un groupe d'ennemis ou un seul ennemi?
Richard Marskell - Drackir
"mob" est un seul ennemi. Le terme a été inventé par Richard Bartle dans MUD1, et est l'abréviation de "mobile" - parce que les foules se déplacent un peu, contrairement à d'autres objets.
Nevermind
2

Cela dépendra du nombre d'ennemis que vous avez et de leur niveau d'activité.

Si vous avez beaucoup d'ennemis, mais qu'ils ne font pas grand-chose la plupart du temps, un système d'événements pourrait être mieux. Si vous avez des ennemis qui font généralement quelque chose, la boucle peut mieux fonctionner car elle rend compte de la complexité du système d'événements et parce que si des événements étaient en place, ils se déclencheraient de toute façon.

Nate
la source