Come posso impedire al giocatore di andare alla deriva a causa della previsione di input locale quando si fermano?


14

Sto lavorando a un motore di gioco multiplayer 2D client-server (che puoi provare qui ). Utilizza WebRTC DataChannel. (Le connessioni sono peer-to-peer, ma il peer host funge ancora da server.)

Il problema più grande (a parte la connettività) è la previsione di input locale. Facciamo il solito: premendo i tasti, i giocatori si muovono all'istante, dicono all'host quali tasti vengono premuti, ricevono i dati dall'host e li confrontano con la posizione storica. La posizione viene corretta nel tempo in caso di differenza. Funziona bene con bassa perdita di pacchetti o PDV , anche se il ping è alto.

In caso di perdita o PDV, la deviazione può essere maggiore. Penso che ciò sia dovuto al fatto che se il primo pacchetto che indica un cambiamento di input viene ritardato o eliminato, l'host lo scopre più tardi e inizia a cambiare quel giocatore più tardi di quanto mostrato dalla loro previsione locale di input.

Se il giocatore si sta muovendo, aumentiamo la quantità di correzione applicata, poiché è meno evidente. Questo sembra coprire gli spazi vuoti quando si inizia a muoversi e durante lo spostamento. Tuttavia, qualsiasi correzione è più evidente se si arrestano bruscamente. Quindi se il PDV o la perdita significano che l'host pensa di essersi fermato più tardi, l'host esegue l'overhoot, restituisce i dati dicendo che sono un po 'più avanti e la correzione rende il giocatore alla deriva un po'. Su connessioni instabili, i giocatori spesso vanno alla deriva dopo essersi fermati.

Non l'ho notato in altri giochi. Come può essere mitigato?


3
Un gioco P2P che ha un server? C'è qualcosa che non va qui.
API-Bestia

Oops, per "server" intendo "il peer host".
AshleysBrain,

2
Beh, non sembra nemmeno un modello peer-to-peer, solo perché uno dei giocatori si pone come il server non lo rende peer-to-peer. La tecnica che stai impiegando è sicuramente una tecnica client-server. In P2P o ti fidi completamente di tutti i clienti (ad es. Ogni peer si chiede l'un l'altro peer dove si trova il loro giocatore) o non ti fidi di nessuno (ad es. Ritardi l'input fino a quando tutti i peer lo hanno ricevuto).
API-Bestia

Ah ... questo è un buon punto in realtà ... Mi sono confuso: le connessioni sono peer-to-peer (che è ciò che fa WebRTC), ma il motore stesso è server-client (uno dei peer è solo il server ). Buon punto.
AshleysBrain,

2
Ciò che questo mi fa pensare è nostra stessa Andrew Russell 's Stick Ninjas tronchi dev su YouTube , in particolare questo, che fissa gli errori di previsione . Il drifting che descrivi suona molto simile a quello che sta succedendo in quel video e Andrew racconta i dettagli. Questi sono correlati, o forse anche lo stesso problema?
Anko,

Risposte:


8

Il livello di rete deve avere un orologio concordato. Possono concordare un valore di clock all'inizio del gioco (e risincronizzarlo periodicamente in caso di drift) in modo che l'host sappia quanto tempo impiega un determinato pacchetto ad arrivare effettivamente e quando il client ha fatto l'azione, e viceversa.

Vedi questo articolo per un modo possibile per sincronizzare gli orologi nei giochi. Ce ne sono altri I mezzi specifici non contano.

La seconda metà del problema è che il server applica l'input oltre il tempo in cui il client ha smesso di applicare l'input. Ciò richiede un buffer di movimenti passati sul server e una certa logica sul client per ignorare gli input di movimento dal server dopo l'ultimo movimento noto.

Innanzitutto, il buffer del server. Il server deve tenere traccia del timbro dell'orologio dell'ultimo input ricevuto dal lettore. Ha anche bisogno di tutti i movimenti che applica a un giocatore, il timbro dell'orologio del movimento. Se viene ricevuto un input, tutti i movimenti recenti applicati con un timbro di orologio più recente del pacchetto di input vengono eliminati e tutti i movimenti vengono riapplicati dal pacchetto di input. Pertanto, se il server si sposta in eccesso del giocatore in base ad alcuni input, l'input aggiornato annullerà quelle mosse e la nuova posizione del giocatore si baserà sulla conoscenza dell'input più recente del server.

Sul lato client, il client conosce l'ultima volta che ha inviato input al server. Poiché ogni aggiornamento del giocatore dal server avrebbe dovuto essere taggato con l'orologio dell'ultimo input di cui il server era a conoscenza, il client può ignorare gli aggiornamenti del server che hanno un tag di input scaduto e attenersi semplicemente alla previsione del client. Alla fine arriveranno nuovi aggiornamenti del server con input aggiornati e il client può correggerli.

Il server deve convalidare gli orologi di input e assicurarsi che non si stiano allontanando troppo dalle aspettative per evitare imbrogli. L'orologio di input non dovrebbe essere drasticamente più grande del tempo di andata e ritorno che dovresti calcolare. Fissare quelli che rientrano in un intervallo ragionevole ( [Now-2*RTT,Now]ad esempio).

I clienti vedranno un sacco di jitter degli avatar di altri giocatori se la latenza è alta poiché riceveranno aggiornamenti dal server basato su input non aggiornati ma non hanno modo di sapere che è obsoleto e quindi il server potrebbe iniziare a inviare posizioni abbastanza diverse in base a l'input aggiornato che ha ricevuto (e la sua eliminazione di una parte della sua cronologia e la sua riproduzione con il nuovo input). Quest'ultimo problema con altri giocatori che vedono il tuo jitter avatar non è davvero risolvibile. La latenza fa schifo e i giocatori bloccati su connessioni ad alta latenza vedranno molti jitter di altri giocatori, anche se il loro giocatore si sta muovendo senza intoppi. L'unica correzione è giocare su connessioni migliori o con peer / server con minore latenza.


1

Ho usato messaggi UDP affidabili per indicare cambiamenti dello stato dei pulsanti e messaggi UDP inaffidabili per la correzione della posizione. Fondamentalmente, i seguenti articoli mi hanno aiutato moltissimo: https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking

Indica la previsione del movimento memorizzando gli stati del giocatore a intervalli di tempo costanti in base all'arrivo dei messaggi di correzione della posizione per circa 20 o 30 salvataggi di stato. Quindi sembra che i tuoi giocatori remoti vivranno in un "passato" non molto lontano applicando costantemente la tecnica di previsione :) In base alla latenza del messaggio netto puoi ottenere la posizione del tuo oggetto approssimativamente nel tempo in cui il messaggio è stato appena inviato dall'host.

L'attuale posizione "sullo schermo" può quindi essere facilmente tradotta nella posizione prevista usando la matematica Lerp (interpolazione lineare). L'idea è di interpolare i valori negli intervalli di tempo tra i pacchetti di correzione. Quindi sembra che l'oggetto visualizzato si muova sempre verso una posizione prevista. Per il valore di interpolazione prendo 1 diviso per "latenza media dei messaggi" diviso per "tempo di rendering medio dei fotogrammi" in modo che il movimento appaia regolare.

In questo scenario il gioco calcola su tutti i client e il server corregge di volta in volta valori quali velocità e posizione.

L'unica cosa che aiuta molto in questo caso: ottimizzare la logica di gioco in modo da poter facilmente annullare gli effetti di latenza assicurando che server e client possano emulare un comportamento simile in base all'input del giocatore.

Ho descritto l'intero schema che ho usato nel mio progetto, quindi spero che troverai la risposta alla tua domanda.

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.