Il pathfinding dice a un personaggio dove andare; gli steering behaviors dicono come muoversi istante per istante. Sono un insieme di regole semplici, ciascuna delle quali produce una forza di sterzata. Combinandole si ottengono movimenti fluidi e credibili: un missile che insegue, un pesce che fugge, uno stormo di uccelli che si sposta compatto. Le idee furono rese popolari da Craig Reynolds, che già nel 1987 presentò il modello dei boids per simulare stormi.
Il modello di base
Ogni agente ha una posizione, una velocità e due limiti: una velocità massima e una forza massima di sterzata. A ogni aggiornamento:
forza = somma dei comportamenti attivi
forza = tronca(forza, forza_max)
velocita = tronca(velocita + forza * dt, velocita_max)
posizione += velocita * dt
La forza limitata impedisce cambi di direzione istantanei: l'agente curva in modo naturale, con un'inerzia che dipende da quanto è basso il limite. Un camion avrà una forza massima bassa, una mosca una molto alta.
Seek e flee
Seek (cerca) è il comportamento fondamentale. Si calcola la velocità desiderata, diretta verso il bersaglio alla massima velocità, e la forza è la differenza rispetto alla velocità attuale:
desiderata = normalizza(bersaglio - posizione) * velocita_max
forza = desiderata - velocita
La sottrazione è il cuore del metodo: l'agente non punta direttamente al bersaglio, ma corregge gradualmente la propria traiettoria. Flee (fuggi) è identico con la direzione invertita, e spesso si attiva solo entro un certo raggio dal pericolo.
Arrive
Con seek l'agente raggiunge il bersaglio a piena velocità, lo supera e torna indietro oscillando. Arrive (arriva) introduce un raggio di rallentamento:
distanza = lunghezza(bersaglio - posizione)
se distanza < raggio_frenata:
velocita_voluta = velocita_max * distanza / raggio_frenata
altrimenti:
velocita_voluta = velocita_max
desiderata = normalizza(bersaglio - posizione) * velocita_voluta
forza = desiderata - velocita
È il comportamento giusto per un personaggio che segue i punti di un percorso calcolato con A* e deve fermarsi con precisione all'ultimo.
Pursuit ed evade
Inseguire la posizione attuale di un bersaglio in movimento è inefficiente: si arriva sempre dove il bersaglio era. Pursuit (inseguimento) stima la posizione futura:
tempo = distanza / velocita_max
previsto = bersaglio.posizione + bersaglio.velocita * tempo
forza = seek(previsto)
Evade (eludi) applica la stessa previsione a flee. Per un missile a ricerca o un predatore, la differenza rispetto a seek semplice è evidente.
Wander
Un animale che vaga senza meta non dovrebbe cambiare direzione a caso a ogni fotogramma: ne risulterebbe un tremolio. Wander (vagabonda) proietta un cerchio davanti all'agente e sposta lentamente un punto lungo la sua circonferenza, aggiungendo ogni volta un piccolo valore casuale all'angolo. L'agente fa seek verso quel punto. Il risultato è un movimento sinuoso e imprevedibile ma continuo.
Evitare gli ostacoli
Per non urtare gli ostacoli, l'agente proietta davanti a sé un «sensore», per esempio un segmento lungo proporzionalmente alla velocità. Se il sensore interseca un ostacolo, si genera una forza laterale che allontana dalla sua superficie. Più l'ostacolo è vicino, più forte è la spinta.
Stormi: i boids
Il modello dei boids mostra come comportamenti complessi emergano da regole locali. Ogni agente considera solo i vicini entro un certo raggio e applica tre forze:
| Regola | Descrizione | Effetto |
|---|---|---|
| Separazione | Si allontana dai vicini troppo prossimi | Evita gli ammassamenti |
| Allineamento | Orienta la propria velocità come la media dei vicini | Lo stormo procede nella stessa direzione |
| Coesione | Si dirige verso il centro di massa dei vicini | Il gruppo resta unito |
Nessun agente conosce la forma dello stormo, eppure il gruppo si muove come un'unità, si divide attorno agli ostacoli e si ricompone. Variando i pesi delle tre regole si passa da banchi di pesci compatti a sciami dispersi.
Poiché ogni agente deve trovare i vicini, con molti agenti serve una griglia spaziale per evitare di confrontare tutti con tutti.
Combinare i comportamenti
Nella pratica un agente usa più comportamenti insieme. Due approcci comuni:
- somma pesata: ogni forza viene moltiplicata per un peso e sommata. Semplice, ma forze opposte possono annullarsi, lasciando l'agente fermo davanti a un ostacolo.
- priorità: si calcolano le forze in ordine di importanza, per esempio prima l'evitamento degli ostacoli, poi la separazione, poi il seek, e si aggiungono finché non si esaurisce la forza massima disponibile.
L'approccio a priorità garantisce che i comportamenti di sicurezza abbiano sempre la precedenza.
Dove usarli
Gli steering behaviors sono ideali per folle, animali, veicoli, proiettili guidati, nemici volanti, gregari che accompagnano il giocatore. Non sostituiscono il pathfinding in un labirinto, ma lo completano: A* fornisce i punti del percorso, arrive e l'evitamento degli ostacoli rendono il movimento tra un punto e l'altro naturale.
In sintesi
- Gli steering behaviors producono forze di sterzata limitate che rendono il movimento fluido.
- Seek, flee e arrive sono la base; pursuit ed evade aggiungono la previsione.
- Wander genera un vagabondaggio continuo, l'evitamento degli ostacoli usa sensori in avanti.
- Separazione, allineamento e coesione bastano a creare stormi credibili.
- Le forze si combinano per somma pesata o, più robustamente, per priorità.