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.