Wie verwalte ich alle NPC / AI-Objekte auf dem Server?

8

Ich schreibe ein einfaches MMO und habe derzeit die Server-Client-Architektur eingerichtet, damit sich mehrere Benutzer sehen und gemeinsam bewegen können. Jetzt ist es an der Zeit, Feinde hinzuzufügen.

Ich habe mich gefragt, ob jemand Links zu Artikeln hat, in denen erläutert wird, wie mit den Hunderten von NPC-Objekten, die in der Welt verwaltet werden müssen, am besten umgegangen werden kann. Ich habe etwas gesucht und konnte nicht viele Informationen darüber finden, wie dies normalerweise gemacht wird.

Die zwei Methoden zur Strukturierung der Implementierung, die ich mir vorstellen kann:

  1. Halten Sie alle instanziierten NPC-Objekte in einer Liste und lassen Sie sie nacheinander von einem NPC-Thread durchlaufen, um festzustellen, ob jede Logik verarbeitet werden muss, und führen Sie die erforderlichen Aktionen aus. Ich bin nicht sicher, ob die Leistung dieses Designs ausreichen würde?
  2. Ereignisbasiertes System. Erstellen Sie eine Methode in der NPC-Klasse, die AI / Logic darauf verarbeitet. Lassen Sie diese Methode aufrufen, wenn ein zugehöriges Ereignis signalisiert wird, entweder auf einem Timer für nicht interagierte AI-Funktionen (z. B. Wandern), oder signalisieren Sie das Ereignis extern vom Paket Handler (Spieler, der sich in der Nähe bewegt oder Spieler, der in Reichweite angreift).

Ist einer dieser Ansätze der richtige Weg? Welche anderen Methoden gibt es dafür?

dgo
quelle

Antworten:

5

Wie immer hängt die Architektur von Ihren Anforderungen ab. Wie viele Mobs wirst du haben? Wie komplex ist ihre KI? Worauf reagiert es? Wie oft ändert es seinen Zustand? Wenn Sie diese Fragen beantworten, haben Sie ein viel besseres Verständnis dafür, was Sie wollen und wie Sie das erreichen.

Im Allgemeinen möchten Sie zumindest eine Art Ereignissystem haben. KI wird normalerweise in Form von Ereignissen definiert: "Wenn A passiert, mache B"; und wenn Sie keine Ereignisse im tatsächlichen Code haben, müssten Sie diese Definitionen irgendwie übersetzen.

Nach meiner Erfahrung können Sie mit einer einfachen Schleifenimplementierung davonkommen, wenn Sie nur wenige und wirklich einfache Mobs haben (im Gegensatz zu dem, was die andere Antwort zu suggerieren scheint). Zum Beispiel haben wir in unserem aktuellen Spiel Hunderte kleiner Instanzen mit jeweils höchstens 10 Mobs. Und diese Mobs sind absolut dumm; Eine KI von 99% von ihnen kann in einem Satz beschrieben werden: "Greife ich jemanden an? Wenn nicht, greife den nächsten Spieler an." In diesem Fall ist eine einfache Schleife mehr als genug - zweimal pro Sekunde suchen wir nach einem neuen Ziel (und ein paar anderen Dingen nach den seltenen "intelligenten" Mobs), und das tut es.

Wenn Sie jedoch mehr und / oder intelligentere Mobs haben, funktioniert der naive Ansatz nicht mehr. Damit die KI auf einen Reiz reagieren kann, müssen Sie Code schreiben, der ihn in Ihrer KI-Schleife erkennt. Zum Beispiel: Angenommen, Ihr Mob sollte etwas tun, "wenn er von einem Spieler getroffen wird". Mit einem Loop-Ansatz gibt es keine einfache Möglichkeit, festzustellen, ob der Mob getroffen wurde. Wenn die KI läuft, können Sie überprüfen, ob sich die Gesundheit des Mobs seit dem letzten Tick verschlechtert hat oder ob der Mob derzeit von jemandem angegriffen wird. Sie können jedoch keine tatsächlichen Treffer erkennen, ohne auf Hacks zurückzugreifen, z. B. jede Trefferinformation irgendwo zu speichern, damit die KI später darauf zugreifen kann.

Zweitens läuft immer eine naive Schleife, egal was passiert. Wenn Sie viele Mobs haben, möchten Sie, dass die KI so schnell wie möglich ausgeführt wird. Der schnellste Code ist der Code, der überhaupt nicht ausgeführt wird. Wenn Sie Mobs haben, die nicht aktiv sind, möchten Sie, dass sie keine oder nur sporadisch KI ausführen (wie in, Wander-Mob-KI sollte nur ausgeführt werden, wenn sie entscheidet, wohin sie als nächstes gehen soll).

Mit dem ereignisbasierten Ansatz können Sie andere Subsysteme jederzeit KI-Ereignisse senden lassen, um das Problem der "Erkennung von Treffern" zu vermeiden. Natürlich müssten für einige Ereignisse immer noch Code erkannt werden. Das berüchtigtste Beispiel ist das Ereignis "Annäherung". Und wenn Sie Ihre KI-Routine nicht in einer Schleife ausführen, wenn nichts passiert, gewinnen Sie an Leistung.

Sie können auch einen hybriden Ansatz verwenden. Anstatt KI-Ereignisse sofort zu behandeln, können Sie sie in eine Art Warteschlange stellen. Wenn dann eine KI-Routine ausgeführt wird (in einer Schleife), werden Ereignisse aus dieser Warteschlange entfernt und einzeln behandelt. Mit dieser Architektur ist die KI-Leistung möglicherweise etwas langsamer, aber vorhersehbarer. Sie können auch garantieren, dass alle KI auf einem einzelnen Thread ausgeführt wird (was ansonsten schwierig sein könnte). Diese Art von Schleife kann auch leicht gedrosselt werden, indem einige Ereignisse übersprungen werden (z. B. behandelt jede KI-Iteration nur drei letzte Ereignisse, wobei der Rest verworfen wird). Oder Ereignisse können priorisiert und weniger wichtige Ereignisse verworfen werden, wenn festgestellt wird, dass die KI zurückbleibt.

Insgesamt ist der Ansatz "Schleife mit Ereigniswarteschlange" wahrscheinlich der flexibelste. Aber ich möchte noch einmal wiederholen: Wählen Sie es nicht einfach blind als "das Beste". Denken Sie zuerst über Ihre Anforderungen nach, und ein einfacherer Ansatz könnte sich als besser herausstellen.

Keine Ursache
quelle
Um diese Antwort zu vervollständigen, können Sie jederzeit Mobs hinzufügen oder aus Ihrer Kontrollschleife entfernen. z.B. Wenn niemand beobachtet, was ein Mob tut, ist es einfach nicht logisch, alles zu tun, was der NPC zu diesem Zeitpunkt tun würde. So können Sie einfach viele Mobs filtern und überprüfen, ob die wichtigen (normalerweise diejenigen, die nahe genug an den Spielern sind) Updates benötigen
Ali1S232
Ist ein "Mob" eine Gruppe von Feinden oder ein einzelner Feind?
Richard Marskell - Drackir
"Mob" ist ein einzelner Feind. Der Begriff wurde von Richard Bartle in MUD1 geprägt und steht für "mobil" - weil sich Mobs im Gegensatz zu anderen Objekten irgendwie bewegen.
Nevermind
2

Es hängt davon ab, wie viele Feinde Sie haben und wie aktiv sie sein werden.

Wenn Sie viele Feinde haben, diese aber die meiste Zeit nicht viel tun, ist ein Ereignissystem möglicherweise besser. Wenn Sie Feinde haben, die normalerweise etwas tun, funktioniert die Schleife möglicherweise am besten, da sie die Komplexität des Ereignissystems herausrechnet und wenn Ereignisse vorhanden wären, würden sie sowieso ständig ausgelöst.

Nate
quelle