Come sempre, l'architettura dipende dalle vostre esigenze. Quanti mob hai intenzione di avere? Quanto è complessa la loro IA? A cosa reagisce? Ogni quanto cambia il suo stato? Rispondi a queste domande e avrai una comprensione molto migliore di ciò che vuoi e come ottenerlo.
In generale, vorresti avere almeno un qualche tipo di sistema di eventi. L'intelligenza artificiale è generalmente definita in termini di eventi: "Quando A accade, fai B"; e se non hai eventi nel codice reale, dovresti in qualche modo tradurre queste definizioni.
Nella mia esperienza, puoi cavartela con una semplice implementazione in loop quando hai pochi mob davvero semplici (contrariamente a quanto sembra suggerire l'altra risposta). Ad esempio, nel nostro gioco attuale abbiamo centinaia di piccole istanze con ognuna al massimo 10 mob. E questi mob sono stupidi; L'intelligenza artificiale del 99% di essi può essere descritta in una frase: "Sto attaccando qualcuno? Altrimenti, attacca il giocatore più vicino". In questo caso un semplice loop è più che sufficiente: due volte al secondo controlliamo un nuovo target (e alcune altre cose per i rari mob "intelligenti"), e questo lo fa.
Tuttavia, quando hai mob più e / o più intelligenti, l'approccio ingenuo smette di funzionare. Affinché l'IA reagisca ad alcuni stimoli, dovresti scrivere un codice che lo rilevi all'interno del tuo ciclo AI. Ad esempio: supponiamo che il tuo mob dovrebbe fare qualcosa "quando viene colpito da un giocatore". Con un approccio ad anello, non c'è modo semplice per determinare se il mob è stato colpito. Quando l'IA è in esecuzione, puoi verificare che la salute del mob sia diminuita dall'ultimo tick o che il mob sia attualmente preso di mira da qualcuno. Ma non puoi rilevare hit reali senza ricorrere a hack, come salvare ogni informazione sui hit da qualche parte affinché AI possa accedervi in un secondo momento.
In secondo luogo, scorre sempre un ciclo ingenuo, qualunque cosa accada. Quando hai molti mob, vuoi che l'IA funzioni il più velocemente possibile ... e il codice più veloce è il codice che non viene mai eseguito. Se disponi di mob che non sono attivi, vuoi che non eseguano l'intelligenza artificiale o che eseguano solo sporadicamente (come in, l'IA mobile errante dovrebbe funzionare solo quando decide dove andare dopo).
Con un approccio basato sugli eventi, puoi avere altri sottosistemi che inviano eventi AI ogni volta che è conveniente, eliminando il problema di "rilevare i colpi". Certo, alcuni eventi richiederebbero comunque il rilevamento del codice: l'esempio più noto è l'evento "approccio". E quando non esegui la tua routine AI in un ciclo quando non succede nulla, ottieni prestazioni.
Puoi anche usare un approccio ibrido. Invece di gestire immediatamente gli eventi AI, puoi inserirli in una sorta di coda. Quindi, quando viene eseguita la routine AI (in un ciclo), rimuove gli eventi da questa coda e li gestisce uno per uno. Con questa architettura, le prestazioni dell'IA potrebbero essere un po 'più lente, ma è più prevedibile; inoltre, puoi garantire che tutta l'IA venga eseguita su un singolo thread (che altrimenti potrebbe essere complicato). Questo tipo di loop può anche essere facilmente limitato saltando alcuni eventi (ad esempio, ogni iterazione AI gestisce solo i tre eventi più recenti, scartando il resto). Oppure gli eventi potrebbero essere prioritari e quelli meno importanti vengono scartati se si rileva che l'IA è in ritardo.
Nel complesso, l'approccio "loop con coda eventi" è probabilmente il più flessibile. Ma voglio ribadirlo: non limitarti a sceglierlo alla cieca come "il migliore". Pensa prima ai tuoi requisiti e un approccio più semplice potrebbe rivelarsi migliore.