Domanda

Come simulare due veicoli controllati dal client che si scontrano (sensibilmente) in una tipica configurazione client / server per un gioco di rete? Ho letto questo eminente post sul blog su come fare fisica di rete distribuita in generale (senza previsione client tradizionale), ma questa domanda riguarda in particolare come gestire le collisioni di oggetti di proprietà.

Esempio

Dire che il client A è 20 ms davanti al server, il client B 300 ms davanti al server (contando sia la latenza che il jitter massimo). Ciò significa che quando i due veicoli si scontrano, entrambi i client vedranno l'altro come 320 ms dietro - nella direzione opposta alla velocità dell'altro veicolo. Testa a testa su un'autostrada svedese significa una differenza di 16 metri / 17,5 iarde!

Cosa non provare

È praticamente impossibile estrapolare le posizioni, dal momento che ho anche veicoli molto complessi con giunti e corpi dappertutto, che a loro volta hanno posizioni lineari e angolari, velocità e accelerazioni, per non parlare degli stati dell'input dell'utente.

È stato utile?

Soluzione 5

Quello che alla fine ho fatto è stato semplicemente saltare la previsione del tutto e semplicemente farlo:

  1. Il cliente ha molto da dire sulla propria posizione,
  2. Il server (quasi) dice qualcosa sulla posizione del cliente proprietario quando un "alta energia" si è verificata una collisione con un altro oggetto dinamico (ovvero non un ambiente statico).
  3. Il client prende meshoffset = meshpos-physpos quando riceve un aggiornamento posizionale dal server e quindi imposta meshpos = physpos + meshoffset ogni frame e diminuisce gradualmente meshoffset .

Sembra abbastanza buono per la maggior parte del tempo (in una situazione di bassa latenza), non ho nemmeno bisogno di slerp i miei quaternioni per ottenere transizioni fluide.

Probabilmente saltare le previsioni dà una terribile esperienza ai clienti ad alta latenza, ma non ho tempo di soffermarmi su questo se avrò mai intenzione di lanciare questo gioco indipendente. Di tanto in tanto è bello creare una soluzione da metà culo che funzioni abbastanza bene ma meglio. ;)

Modifica: alla fine ho finito per aggiungere la "proprietà" caratteristica che Glen Fiedler (il blogger menzionato nella domanda) ha implementato per Mercenaries 2: ogni cliente ottiene la proprietà di oggetti (dinamici) con cui si scontrano per un po '. Ciò era necessario poiché la penetrazione altrimenti diventa profonda in situazioni di latenza elevata e velocità elevate. Quella solennità funziona alla grande come si potrebbe pensare quando si vede la presentazione video GDC, può sicuramente consigliarla!

Altri suggerimenti

Non conosco una soluzione perfetta e ho la sensazione che non esista. Anche se fosse possibile prevedere con precisione la posizione futura del veicolo, non si sarebbe in grado di prevedere il modo in cui l'utente utilizzerà i controlli. Quindi il problema si riduce alla minimizzazione degli effetti negativi del ritardo client / server. Con questo in mente, mi avvicinerei a questo dalla posizione del principio del minimo stupore (parafrasato da Wikipedia):

  

Nella progettazione dell'interfaccia utente, il principio del minimo stupore (o sorpresa) afferma che, quando due elementi di un'interfaccia sono in conflitto o sono ambigui, il comportamento dovrebbe essere quello che sorprenderà meno l'utente umano nel momento in cui sorge il conflitto .

Nel tuo esempio, ogni utente vede due veicoli. Loro e quelli di un altro giocatore. L'utente si aspetta che il proprio veicolo si comporti esattamente come lo controlla, quindi non siamo in grado di giocare con quell'aspetto della simulazione. Tuttavia, l'utente non può sapere esattamente come l'altro utente sta controllando il il loro veicolo, e vorrei usare questa ambiguità per nascondere il ritardo all'utente.

Ecco l'idea di base:

  1. Il server deve prendere la decisione su una collisione imminente. L'algoritmo di rilevamento delle collisioni non deve essere perfetto al 100%, deve solo essere abbastanza vicino da evitare evidenti incoerenze.
  2. Una volta che il server ha stabilito che due veicoli si scontreranno, invia a ciascuno dei due utenti un messaggio che indica che una collisione è imminente.
  3. Sul client A, la posizione del veicolo B viene regolata (realisticamente) per garantire che si verifichi la collisione.
  4. Sul client B, la posizione del veicolo A viene regolata (realisticamente) per garantire che si verifichi la collisione.
  5. Durante le conseguenze della collisione, la posizione di ciascun veicolo può essere regolata, se necessario, in modo che il risultato finale sia in linea con il resto del gioco. Questa parte è esattamente ciò che MedicineMan ha proposto nella la sua risposta .

In questo modo, ogni utente ha ancora il controllo completo del proprio veicolo. Quando si verifica la collisione, non sarà inaspettato. Ogni utente vedrà l'altro veicolo muoversi verso di loro e avrà comunque la sensazione di una simulazione in tempo reale. La cosa bella è che questo metodo reagisce bene in condizioni di basso ritardo. Se entrambi i client dispongono di connessioni a bassa latenza al server, la quantità di regolazione sarà ridotta. Il risultato finale, ovviamente, peggiorerà all'aumentare del ritardo, ma ciò è inevitabile. Se qualcuno sta giocando un gioco d'azione frenetico su una connessione con diversi secondi di ritardo, semplicemente non otterrà la piena esperienza.

Forse la cosa migliore che puoi fare non è mostrare in tempo reale l'effettiva collisione, ma dare l'illusione che le cose stiano accadendo in tempo reale.

Poiché il client è dietro il server (ritardo) e il server deve mostrare il risultato della collisione, forse quello che puoi fare, lato client, è mostrare un flash o un'esplosione o qualche altro elemento grafico per distrarre l'utente e acquista abbastanza tempo sul lato server per calcolare il risultato della collisione. Al termine della previsione, lo rispedisci al lato client per la presentazione.

Mi dispiace rispondere con " Cosa non provare " ;, ma non ho mai sentito parlare di una soluzione che non preveda la previsione del risultato sul lato client. Considera un esempio semplificato:

Il cliente A è fermo e sta guardando il veicolo del cliente B avvicinarsi a una scogliera. Il veicolo del cliente B è in grado di ridurre la velocità a 0 all'istante e lo fa nell'ultimo momento possibile prima di superare la scogliera.

Se il Cliente A sta tentando di mostrare lo stato del Cliente B in tempo reale, il Cliente A non ha altra scelta che prevedere che il Cliente B è caduto dalla scogliera. Lo vedi molto nei MMORPG progettati in modo tale che il personaggio di un giocatore sia in grado di fermarsi immediatamente quando corre a tutta velocità. Altrimenti, il client A potrebbe mostrare lo stato del client B quando arrivano gli aggiornamenti di stato, ma questo non è praticabile, poiché il client A deve essere in grado di interagire con il client B in tempo reale nel tuo scenario (suppongo).

Potresti provare a semplificare i modelli di collisione in modo che l'estrapolazione sia possibile per la previsione in tempo reale? Forse rendi le tue "articolazioni e corpi ovunque" " hanno modelli fisici meno intensivi del processore, come alcuni cubi o sfere. Non ho familiarità con il modo per migliorare l'efficienza del rilevamento delle collisioni, ma suppongo che sia stato realizzato rilevando le collisioni di modelli meno complessi rispetto ai modelli visivi.

Riguardo a " Cosa non provare " ;. Stai assumendo che devi prevedere perfettamente, ma non troverai mai una soluzione perfetta in un gioco con una fisica complessa. Un'approssimazione è probabilmente la migliore che puoi fare (ad esempio, la maggior parte dei motori di fisica commerciale può dare forma alla scena fisica e restituire il primo punto di collisione).

Ad esempio, ho implementato alcune parti critiche della fisica della rete per Mercenaries 2 sotto la guida di Glenn (il poster del blog che hai citato). Era impossibile spingere tutto il necessario stato fisico attraverso il filo per un solo corpo rigido. La fisica di Havok genera gradualmente punti di contatto per ogni frame, quindi l'attuale "contatto collettore" è una parte necessaria dello stato fisico per mantenere deterministica la simulazione. Sono anche troppi dati. Invece, abbiamo inviato la trasformazione e le velocità desiderate e abbiamo usato forze e coppie per spingere delicatamente i corpi in posizione. Gli errori sono inevitabili, quindi è necessario un buon schema di correzione degli errori.

Pochi pensieri.

  1. Peer to peer è meglio nel gestire la latenza & amp; alte velocità.

Quindi, se questo è il tuo motore, passa a peer to peer. Quindi estrapolare il veicolo dell'altro peer in base all'input del pulsante per spostarsi in avanti dove si trova ora. La collisione impostata in modo tale da scontrarsi con l'altro veicolo come se fosse il mondo. Cioè prendi il colpo.

Ciò significa che quando ti scontri con l'altro, rimbalzi, sulla rete del peer rimbalzano su di te, quindi sembra approssimativamente corretto. Minore è la latenza, meglio funziona.

  1. Se vuoi andare client / server, questo sarà inferiore a p2p

Cose da provare o) Estrapolare i client in avanti come in p2p per eseguire il rilevamento delle collisioni. o) Invia i risultati delle collisioni ai clienti ed estrapola in avanti

Nota, questo non sarà MAI buono come p2p. Fondamentalmente ad alta velocità e amp; latenza = errore, quindi rimuovere la latenza è la strategia migliore. P2P lo fa.

Oltre a prevedere sul lato client dove potrebbe trovarsi l'altro utente e inviare le informazioni sulla collisione e il modo in cui le hai gestite al server, ciò che la maggior parte dei mmo fa per gestire il ritardo è che hanno il server eseguito "in passato" ; com'era. Fondamentalmente tamponano gli input recenti ma reagiscono solo a ciò che è accaduto .1sec in passato. Ciò ti consente di "sbirciare nel futuro" quando è necessario (vale a dire quando sta per verificarsi una collisione nel periodo di tempo, è possibile esaminare l'input buffer per vedere cosa accadrà e decidere se la collisione è reale).

Naturalmente, questo aggiunge un ulteriore livello di complessità al tuo programma in quanto devi considerare quali dati inviare ai tuoi clienti e come dovrebbero reagire ad essi. Ad esempio, potresti inviare l'intero "futuro" buffer ai client e far loro vedere quali possibili collisioni accadranno effettivamente e quali no.

Ross ha un buon punto. Potresti semplificare il modello che utilizzi per rilevare le collisioni astraggendolo ad un volume più semplice (ovvero il contorno ruvido del veicolo). Quindi puoi fare le previsioni in base al volume semplice e ai calcoli dettagliati sui volumi esatti mentre l'utente è distratto dall'esplosione. Potrebbe non essere perfetto, ma ti consentirebbe di accelerare il rilevamento delle collisioni.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top