La sezione Intent per il pattern Command nel libro Go4 recita:
Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.
Interrompiamo un po 'di quello e guardiamolo nel contesto della programmazione del gioco.
Possibilità di parametrizzare il codice di richiamo
Ciò consente di configurare in modo dinamico la cosa che richiama il comando con un'azione da eseguire. Questo può essere ottenuto anche con i callback. Gli oggetti di comando possono servire come in sostituzione OO per i callback in una lingua che non li supporta in un modo che è necessario (ad esempio, nessun supporto per le funzioni di ordine superiore o nessun supporto per le chiusure); ma se hai bisogno di accedere o manipolare lo stato associato al comando in un secondo momento, o di supportare un'interfaccia più complessa, allora solo Execute (), avere una classe Command può aiutarti.
Nel libro, il modello introdotto nel contesto dello sviluppo di un framework per i menu delle applicazioni, in cui una voce di menu può essere configurata da un comando. Il bit importante è che la voce di menu non ha idea di cosa faccia o di quale sia l'oggetto di destinazione - non ha alcuna comprensione dell'operazione che esegue, sa solo che qualcosa dovrebbe accadere quando viene cliccato.
Puoi variare questa struttura di base; per esempio, il mio ricevitore può essere indirizzato indirettamente, tramite un ID di qualche tipo (e recuperato da qualche altro componente).
Nei giochi, e in particolare nell'IA del gioco, uno scenario piuttosto simile è quando si vuole supportare scripting - un comando può incapsulare uno script fornito dall'utente (e magari portare con sé alcuni metadati, e possibilmente un riferimento al motore di scripting). Qui, il codice chiamante sa quando e in quali circostanze eseguire uno script, ma non ha idea di cosa fare e quali entità influenzare. (Certo, ci sono altri modi per farlo).
Ciò promuove la separazione delle preoccupazioni tra i diversi sistemi coinvolti (AI, Scripting).
Ma anche, considera qualcosa di meno esotico. Combinazioni di tasti. Potrebbero esserci più chiavi (o più trigger su diversi dispositivi di input) che invocano la stessa azione, oppure le azioni possono essere dipendenti dal contesto (la stessa chiave fa una cosa diversa in situazioni diverse). Inoltre, il giocatore può cambiarli in qualsiasi momento. Un modo per gestirli è disporre di un set di oggetti comando che puoi semplicemente inserire e uscire dal sistema che gestisce l'input, associandoli dinamicamente a vari trigger.
La capacità di effettuare richieste di coda
Una volta che hai questa infrastruttura in atto per mappare gli input ai comandi, puoi sfruttarli nel tuo sistema di IA per controllare gli NPC.
Ora hai detto:
Usually when programming AI you want the instructions to be executed instantly
Bene, non devono essere eseguiti proprio nel momento le decisioni sono prese - solo all'interno del ciclo corrente nel ciclo di gioco. Inoltre, se il gioco utilizza il modello ECS, un approccio al flusso di comandi potrebbe essere una buona idea. Inoltre, alcuni giochi eseguono i loro motori di intelligenza artificiale con una frequenza di aggiornamento diversa da quella del renderizzatore e del resto del gioco, e l'accodamento dell'uscita AI come comandi può essere un buon modo per avvicinarsi a questo.
Supporto per la registrazione
Questo può significare letteralmente il logging, ma pensiamo oltre. Un log è un flusso di eventi registrato. Questo può essere potenzialmente (quando costruito con un po 'di cura), riprodotto . Riproduci e amp; supporto demo pronto per l'uso! Aggiungi alcuni metadati di temporizzazione e con un certo sforzo questo può anche supportare cose come la meccanica di riavvolgimento temporale, in cui il giocatore può riavvolgere il tempo (fino a un certo punto) per riprovare lo stesso scenario (qualcosa sulla falsariga di ciò che è possibile in Braid o in GRID 2).
Extra extra
La possibilità di supportare annulla / ripristina è piuttosto auto-esplicativa, quindi non ci andrò.
Un'altra cosa interessante che puoi fare è combinarla con il pattern Composite, che ti consente quindi di avere comandi compositi - che sono fatti di sottocomandi. Questo può essere semplicemente considerato come una comodità per te come sviluppatore, ma questo potrebbe anche fornire supporto per la costruzione di editor dove gli utenti possono creare questi comandi compositi in una GUI, o anche abilitare l'utente a incorporare questo in un gameplay, dove il giocatore può creare comportamenti personalizzati come parte di una meccanica e far sì che il gioco li ricordi (dato che puoi serializzare e deserializzare i comandi, inclusi i comandi compositi).
Un altro vantaggio del trattamento dei comandi come oggetti o dati è che è possibile eseguirne in modo flessibile in parallelo (se le attività sono parallelizzabili), il che può migliorare le prestazioni.