Come viene evitato localmente RTS?


15

Attualmente, sto simulando le forze di impatto fisico per evitare le unità locali, ma questo metodo a volte spinge le unità fuori formazione e ha effetti molto indesiderati quando le unità si raggruppano.

Per i giochi RTS come Starcraft 2, come viene fatto l'elusione locale? La fisica è simulata o un controllore onniciente decide dove dovrebbe essere tutto? So che questa domanda potrebbe essere un po 'ampia, quindi chiedo specificamente come ottenere i comportamenti di evitamento locali di Starcraft 2; anche se tutto ciò che funziona sarà molto apprezzato.

Non sto cercando alcun codice, ma solo risorse utili o spiegazioni su come Starcraft 2 (o giochi simili) gestisce l'evitamento locale.

Attualmente, ho implementato il rilevamento delle collisioni (con il vettore di penetrazione), le forze di collisione e il movimento per velocità. Ogni unità viene controllata contro un'altra per una collisione: se si scontrano, gli oggetti vengono immediatamente sfalsati dal vettore di penetrazione, quindi viene applicata la forza di collisione. Quindi un altro loop sposta gli oggetti in base alle loro velocità e applica la resistenza alle velocità. L'offset mitiga il problema delle forze di collisione eccessive applicate alle unità raggruppate, ma le unità a volte continuano a sparare.

La soluzione che sto cercando deve soddisfare i seguenti requisiti (come in Starcraft 2):

  • Gli oggetti non devono sovrapporsi; o almeno le sovrapposizioni devono essere eventualmente risolte.
  • Gli oggetti non si allontanano più del necessario, quindi 2 unità possono stare in piedi e muoversi l'una accanto all'altra in una formazione.
  • Non dovrebbero esserci comportamenti strani quando gli oggetti si aggregano verso la stessa destinazione.
  • Può supportare unità di diverse dimensioni e persino diverse forme convesse.

Ciò a cui ho pensato finora è invece di rilevare le collisioni, rilevare le collisioni future in modo che la sovrapposizione non avvenga mai. Quindi applica il vincolo, assicurandoti che le velocità delle 2 unità non si sovrappongano. Sto ancora armeggiando con l'algoritmo per limitare i movimenti oltre la sovrapposizione.


"comportamento di floccaggio" (termine di Google) è un problema molto ampio,
maniaco del cricchetto,

Questo era nella coda dei voti ravvicinati come "troppo ampio" - Sono propenso ad essere d'accordo. Tentativo di restringere: cosa hai provato? Quali "effetti indesiderati" stai cercando di evitare? Ho ragione nel dire che vuoi che le unità rimangano in formazione?
Anko,

I giochi RTS spesso funzionano su ogni client eseguendo la stessa simulazione deterministica su ogni macchina. Quindi, fondamentalmente, se riesci a risolverlo per una singola macchina, puoi applicare la stessa soluzione alle situazioni multiplayer, qualunque sia la tecnica di evitamento locale con cui finisci.
Alan Wolfe,

Grazie per il feedback sulla domanda. Ho ristretto un po 'la domanda e ho spiegato in particolare cosa sto cercando di realizzare.
JPtheK9,

Questa è una grande risorsa: red3d.com/cwr/steer
tbkn23

Risposte:


11

Sembra che quello che stai cercando sia l' algoritmo Optimal Reciprocal Collision Avoidance . Anche il documento precedente merita una lettura. Sebbene l'articolo possa essere un po 'coinvolto, la teoria alla base dell'algoritmo è abbastanza semplice:

Supponiamo di avere già una simulazione (gioco) con agenti (unità) che hanno una sorta di volume limite attorno a loro. Questo volume limite è probabilmente quello che stai già utilizzando per eseguire il rilevamento e la risposta delle collisioni. Per ciascun agente, definire una velocità preferita v_pche può o meno essere basata sull'obiettivo dell'agente.

Ora, per eseguire la simulazione:

  1. Per ogni agente, supponendo che sia fermo, calcola tutte le velocità che lo farebbero scontrare in qualsiasi punto in futuro con uno qualsiasi degli altri agenti in movimento. Questo può essere rappresentato nello "spazio di velocità" come un insieme di semipiani che si intersecano (noto anche come un ostacolo di velocità ).
  2. Determina il punto in questo spazio più vicino a v_p, questa è la nuova velocità dell'unità.

Se tutti gli agenti eseguono lo stesso algoritmo, sceglieranno velocità che si completano a vicenda ed eviteranno altri agenti. In alcune situazioni, puoi causare oscillazioni come quella cosa imbarazzante che accade quando entri direttamente in qualcuno nell'atrio e provi entrambi ad allontanarti nella stessa direzione, ma i documenti spiegano come evitarlo.

Per calcolare le due fasi dell'algoritmo sopra, è possibile utilizzare le somme di Minkowski per determinare quale sia l'ostacolo della velocità, quindi utilizzare un modello di programmazione lineare (come l' algoritmo simplex ) per determinare il punto più vicino a v_pquello che evita l'ostacolo della velocità. Inoltre, il codice per evitare le collisioni è disponibile per il tuo esame ed è stato portato su C # per essere utilizzato nei motori di gioco come Unity. Questa tecnica è stata utilizzata almeno in Warhammer 40,000: Space Marine e forse in altri giochi .


È stato un articolo fantastico e mi sembra di averne letto metà dalla tua spiegazione. Grazie per questa informazione
JPtheK9,

0

Non so come funzionano le tue unità ma presumo che siano come una macchina a stati:

Stati possibili

  • In esecuzione verso (x, y, z)
  • Attacco (nemico_id)
  • Collezionare risorse (ressource_id)

Se presti attenzione a come Starcraft affronta questo problema, scoprirai che:

  1. Se c'è spazio per muoversi in una direzione, il personaggio si sposta in quella direzione.
  2. Se non c'è spazio, l'unità sulla strada si sposterà per fare spazio
  3. Se l'unità che deve spostarsi per fare spazio ha già un comando, manterrà il comando, ma modificalo leggermente per far posto.

Qui scenario 1:

inserisci qui la descrizione dell'immagine

Ho spazio per andarci? Sì ? Allora vai

Scenario 2:

inserisci qui la descrizione dell'immagine

Ho spazio per andarci? No ? Ehi, puoi farmi spazio, mi stai bloccando. Ho già un ordine per andare avanti ma ti accontenterò.

Quindi cosa dovrai implementare:

  • Le unità devono essere consapevoli dell'ambiente circostante
  • Le unità devono avere un modo per comunicare tra loro
  • È necessario implementare un modo per continuare a eseguire un comando mentre si alloggia un'altra unità

Grazie per le informazioni e la visualizzazione. In questo momento sto usando il rilevamento delle collisioni per scoprire se un'unità può spostarsi in un altro posto o se un'altra unità la sta occupando. La cosa principale che sto cercando di capire è un algoritmo di qualche tipo per dire all'altra unità da quale distanza muoversi o da quale velocità regolare. In altre parole, come l'unità di blocco ospiterà l'unità che cerca di passare.
JPtheK9,

Poiché questo comportamento viene calcolato ogni aggiornamento di fisica, non è necessario dire la distanza, si sposterà fino a quando non sarà fuori mano. Per la direzione, scansionate semplicemente moltiplicando la velocità delle due unità, questo vi darà il punto a metà strada in modo che continui a muoversi mentre vi accomodate. Dopodiché puoi giocare con quello per farlo in modo che si attacchi più all'ordine o si muova più velocemente.
Antoine,

Cosa intendi con "mosse finché non è fuori mano"? Come si muove l'unità in primo luogo?
JPtheK9,

Scusate ho dimenticato di menzionare: le unità non sono macchine a stati. Hanno molte abilità nel loro armadietto che sono simulate in ogni fotogramma - eccetto queste abilità hanno effetto solo quando attivate, sia che la destinazione sia a X distanza o con l'esistenza di un bersaglio. Il movimento di un'unità è il risultato della sua velocità che può essere modificata da un'abilità.
JPtheK9,

0

Un modo per farlo è quello di avere le formazioni auto-formanti delle unità e di farle tentare di rimanere in una posizione rispetto al centro della formazione . Quindi, invece di spostare ciascuna unità individualmente, sposta il centro della formazione attorno.

Ecco un modo di base per farlo usando una formazione a scatola e semplici molle per mantenere le unità nelle loro posizioni appropriate:

// Defines a phalanx (box) formation
class Formation
    // Center of the box in the world
    Position center;
    // Width in # of units
    int width;
    // Height in # of units
    int height;
    // Space between units
    float scale;
    // How much force units will apply to stay near
    // their assigned spot.
    float springforce;

    // Return a position of a unit at the given row and column
    // Todo: add a rotation to this formation so it can rotate when moving.
    Position GetUnitPhalanxPosition(int row, int column)
        return new Position(center.X + column * scale - width * scale /2, 
                            center.Y + row * scale    - height* scale / 2);

// Represents a simple point object with a velocity and position;
// it belongs to a formation.
class Unit
    Position pos;
    Velocity vel;
    Formation formation;
    // What's our assigned spot in the formation?
    int row;
    int column;

    void Update(float dt)
        // Get the desired target position in the formation
        Position target = formation.GetUnitPhalanxPosition(row, column);
        // Apply a spring force toward the position (todo: you might want to damp this)
        vel += (target - position) * dt * formation.springforce;
        // Move along the velocity vector.
        pos += vel * dt;

Grazie! Questa è una soluzione davvero interessante e creativa. Ho implementato qualcosa di simile a questo per il comportamento / le formazioni della folla, ma ho ancora il problema della sovrapposizione delle unità. Cosa dovrebbe accadere se 2 formazioni si incontrano?
JPtheK9,

Penso che dipenda dal design. La cosa più semplice sarebbe semplicemente applicare un'altra forza di governo lontano dalle unità vicine in altre formazioni come in questa immagine . Un'altra cosa che potresti fare è unire le formazioni quando vengono selezionate dal giocatore o persino formare "meta-formazioni"
mklingen,

Le meta-formazioni sembrano davvero complicate e buggy: C. L'immagine che hai collegato potrebbe essere esattamente quello di cui ho bisogno. Farò qualche ricerca in più sulle forze di governo. Hai il link all'articolo dell'immagine?
JPtheK9,

Ho un problema simile al tuo, sarebbe interessante sapere come l'hai risolto. Mi è venuta in mente un'idea di questo articolo dopo aver letto questo articolo: forse combinando Pathfinding (A *) per una pianificazione del percorso macro mentre si utilizza la forza di riavvolgimento per evitare la
microcollisione

0

Conosco alcune persone che disapprovano il dumping dei link, tuttavia ho trovato un approccio multi-agente basato sul campo potenziale per i robot di gioco in tempo reale (ISBN 978-91-7295-160-0) per essere un documento molto illuminante, e ovviamente trasmette molto più di quanto potessi approfondire. Il documento esplora l'utilizzo di campi potenziali artificiali (un concetto originato dalla robotica), per facilitare l'evitamento delle collisioni locali in un contesto di sviluppo del gioco.


Grazie! La ricerca è utile quanto la spiegazione per me. Mi tufferò in questo documento.
JPtheK9,

Ho già impostato una mappa di influenza, ma questo sembra troppo complicato per i miei gusti. La cosa principale è generare campi potenziali per le diverse unità per spostarli e anche convertire i dati dal campo potenziale in una velocità a cui muoversi. Fondamentalmente, non penso che funzionerebbe per unità di dimensioni diverse. È un'ottima lettura anche se con molte idee interessanti.
JPtheK9,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.