Eseguire una simulazione fisica su client e server?


13

Sto implementando un clone di asteroidi multiplayer per conoscere l'architettura di rete client / server nei giochi. Ho trascorso del tempo a leggere le pubblicazioni di GafferOnGames e Valve sulla loro tecnologia client / server. Ho problemi con due concetti.

  1. Attualmente ho un server di gioco autorevole che simula la fisica con box2d e invia lo stato del mondo ai clienti circa 20 volte al secondo. Ogni client tiene traccia delle ultime istantanee ricevute e scorre tra due stati per rendere più fluido il movimento degli sprite. Tuttavia non è così semplice. Può essere fluido per un po ', quindi a scatti un po', poi di nuovo a smooth, ecc. Ho provato sia TCP che UDP, entrambi sono quasi uguali. Qualche idea di quale potrebbe essere il mio problema? (Nota: l'ho implementato per primo per giocatore singolo e il movimento dello sprite è perfettamente fluido a 60 fps quando aggiorno il mondo della fisica solo 20 volte al secondo).

  2. Al fine di risolvere il primo problema, ho pensato che forse il client dovrebbe eseguire anche una simulazione box2d e aggiornare semplicemente le posizioni dei suoi sprite in modo che corrispondano alle istantanee del server quando non corrispondono. Ho pensato che potesse essere più fluido poiché la mia implementazione single player è fluida. E 'questa una buona idea?

    Anche se non risolverà il problema sopra riportato, è necessario per la previsione sul lato client? Ad esempio, se un giocatore tenta di muovere la propria nave, come farà a sapere se ha colpito un asteroide, un muro o una nave nemica senza una simulazione fisica? Sembra che la loro nave sembrerebbe passare attraverso l'oggetto con cui dovrebbe scontrarsi prima di ricevere un'istantanea dal server che dice che hanno colpito l'oggetto.

Grazie!

Risposte:


10

Esegui sicuramente la simulazione sia sui client che sul server. Qualsiasi altra cosa ha una latenza troppo lunga. Dovresti essere sicuro che le simulazioni corrispondano inserendo oggetti nello stesso ordine, usando una fase temporale fissa ed evitando il confronto dei puntatori. Non ho provato questo con Box2D ma è generalmente possibile ottenere lo stesso comportamento su tutte le macchine in una simulazione fisica. Tutta la matematica si basa generalmente su float binari32 IEEE 754 e il loro comportamento è strettamente definito per operazioni come +-*/per citarne alcuni. È necessario essere attenti a sin,cose quelli difficili, dal momento che possono differire tra i tempi di esecuzione (questo è particolarmente importante quando si sviluppa per più piattaforme). Assicurati inoltre di utilizzare un'impostazione rigorosa per le ottimizzazioni float nel tuo compilatore. È ancora possibile sincronizzare gli oggetti inviando periodicamente lo stato degli oggetti dal server. Non aggiornare a meno che la differenza non sia maggiore di una soglia per evitare la balbuzie non necessaria.

Un problema che viene in mente è la creazione di nuovi oggetti e come ciò cambierà la simulazione tra i client. Un modo per risolvere questo problema è consentire al server di creare tutti gli oggetti. Se la fase temporale corrente è t, il server pianificherà un oggetto da aggiungere a t+d. Pertanto, un elenco di nuovi oggetti, con oggetti da aggiungere e quando aggiungerli, può essere gestito su tutti i client e aggiornato dal server con largo anticipo. Se dè abbastanza grande, minimizzi il rischio di risultati diversi. Se davvero non riesci a gestire la differenza, puoi forzare un client ad attendere informazioni sui nuovi oggetti per un determinato passaggio temporale prima di simulare tale passaggio temporale.


Grazie per la risposta. Non credo che box2d possa garantire gli stessi risultati su CPU diverse, il che sarebbe lo scenario per noi dal momento che stiamo scrivendo un gioco desktop. Spero che le differenze siano minime e facilmente correggibili con aggiornamenti periodici da un server autorevole, ma non l'ho mai provato.
Venesectrix,

Erin Catto pensa che cercare di mantenere sincronizzato l'intero stato di più mondi Box2D sia una battaglia persa ( box2d.org/forum/viewtopic.php?f=3&t=8462 )
Pavel

L'istruzione "IEEE 754 binary32 float [..] comportamento è rigorosamente definita per operazioni come +-*/" è completamente falsa. Tutte queste operazioni in IEEE-754 potrebbero variare in base all'implementazione. Vedi qui e qui per maggiori informazioni.
BlueRaja - Danny Pflughoeft,

1
No. È completamente vero. Il problema descritto dal tuo collegamento è legato alle diverse modalità della fpu x87 e alle implementazioni dei trascendentali. IEEE 754 binary32 è rigorosamente definito per le operazioni di base. Sta a te impostare le modalità corrette e utilizzare le istruzioni giuste in modo da seguire lo standard. Semplicemente usando le istruzioni SSE e non la fpu x87 aiuta molto.
rasmus

4

Probabilmente non sembra così bello poiché l'interpolazione tra loro si basa sul fatto di avere sempre il prossimo set di dati da interpolare. Ciò significa che, se c'è un picco breve, tutto deve aspettare per recuperare.

C'è un vecchio articolo su GameDev sull'uso di spline cubiche per prevedere la posizione di un oggetto oltre il punto in cui si sono registrati i dati per l'ultima volta. Quello che fai allora è usare quella posizione e quindi regolare la spline quando ottieni nuovi dati per tenere conto della sua nuova posizione. Probabilmente è anche molto più economico rispetto all'esecuzione di una seconda simulazione fisica, e significa che non devi decidere su chi ti fidi, dal momento che hai implementato esplicitamente il client inventandolo man mano che procede. :)


Questo potrebbe essere il caso. Quello che sto cercando di fare è ritardare fino a quando non ho ricevuto 3 snapshot dal server. Nel punto che passo dallo scatto 1 allo scatto 2. Quindi dallo scatto 2 allo scatto 3. Se in qualsiasi momento mi manca un pacchetto, posso passare da 1 a 3, anziché da 1 a 2, se ciò ha senso. Tuttavia, potrei non implementarlo correttamente. Grazie per il link all'articolo!
Venesectrix,

1

Ho fatto alcune cose simili da solo e ho eseguito Box2D solo sui client. Il modo in cui l'ho fatto è stato quello di consentire al client di eseguire la propria simulazione praticamente da solo, inviando la velocità (e la rotazione) corrente su ogni pacchetto di sincronizzazione al server. Il server invia quindi queste informazioni ad altri giocatori, che impostano le velocità appena ricevute sulle entità replicate. È stato molto fluido, senza differenze evidenti tra i clienti.

Naturalmente, il problema qui è che non esiste un controllo centralizzato sulle entità, ma penso che potrebbe essere fatto anche sul lato server eseguendo anche una simulazione lato fisica della fisica


Grazie per il tuo contributo. Richiederemo un controllo centralizzato per evitare cheat, quindi dobbiamo avere almeno una simulazione del server per sapere se ciò che i client dicono che stanno facendo è possibile o meno.
Venesectrix,

1

Personalmente preferirei eseguire le simulazioni solo sul server e fare in modo che trasmetta qualsiasi cambiamento sulle velocità / accelerazioni lineari / angolari degli oggetti coinvolti ogni volta che si verificano. È, quando un determinato oggetto, per qualsiasi motivo, modifica una qualsiasi delle sue proprietà fisiche (come le velocità e le accelerazioni di cui sopra), questa specifica modifica verrà inviata dal server al client e il client cambierà il suo lato del dati dell'oggetto di conseguenza.

Il vantaggio rispetto alla tua attuale implementazione è che annullerà la necessità di interpolazioni lato client e genererà un comportamento molto fedele sugli oggetti. Il problema è che questo metodo è piuttosto vulnerabile alle latenze, che diventano un grosso problema quando i giocatori sono geograficamente troppo distanti tra loro.

Per quanto riguarda la domanda 1, dico che il problema sarebbero le fluttuazioni della latenza, perché non vi è alcuna garanzia assoluta che ci sarà un intervallo di 20 secondi esattamente perfetto tra ogni ricezione dell'istantanea. Permettetemi di illustrare (essendo "t" il tempo misurato in millisecondi):

1) A t = 20 dall'inizio del gioco, il cliente ha ricevuto un'istantanea e ha eseguito l'interpolazione con successo e senza intoppi.

2) A t = 40, c'era una latenza tra il server e il client e l'istantanea arrivava effettivamente a t = 41.

3) A t = 60, il server ha inviato un'altra istantanea, ma un secondo della simulazione è stato sprecato sul lato client a causa della latenza. Se l'istantanea arriva a t = 60, il client non eseguirà un'interpolazione degli istanti 40 e 60, ma in realtà dagli istanti 41 a 60, generando un comportamento diverso. Questa inesattezza su potrebbe essere la causa dell'eventuale "scossone".

Per quanto riguarda la domanda 2, la tua idea potrebbe funzionare se implementassi qualcosa che monitorasse efficacemente se ciascun oggetto è realmente sincronizzato client-server senza dover inviare pacchetti ogni frame che informi sulla posizione degli oggetti. Anche se lo fai a intervalli discreti, non solo eseguirai lo stesso problema della domanda 1, ma avrai anche quantità troppo grandi di dati da trasferire (il che è una cosa negativa).


Non sono sicuro di seguire quello che stai dicendo nel tuo primo paragrafo. Se la simulazione viene eseguita solo sul server e si trasmettono solo variazioni di velocità / accelerazione, come fa il client a sapere dove devono essere disegnati gli sprite? I clienti dovrebbero simulare gli oggetti in base alla velocità / accelerazione ricevuta per disegnarli correttamente. Penso che potresti avere ragione nel ricevere istantanee a intervalli diversi da quello che mi aspetto. Qualche idea su come gestirlo?
Venesectrix,

I client conoscono le posizioni iniziali e attuali, le velocità e le accelerazioni degli oggetti e aggiornano la posizione che ritiene che gli oggetti siano (indipendentemente dal server) di conseguenza. Il server alla fine modificherà tali proprietà sui client attraverso i messaggi, perché è il server che sta effettuando il rilevamento della fisica e delle collisioni (che sono tenuti a cambiare prima o poi la velocità / accelerazione e la direzione di un determinato oggetto)
UBSophung
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.