Attualmente sto lavorando su un platform multiplayer piuttosto semplice. Ho letto parecchi articoli sulle tecniche usate per nascondere la latenza, ma non riesco ancora a capire meglio alcuni concetti. Trovo l'argomento molto interessante e mi piace provare le idee da solo, ma penso che chiedere a gamingev stackexchange sarà più efficiente per la mia domanda. Farò del mio meglio per descrivere la mia situazione attuale e quale domanda è sorta lungo il cammino.
In questo momento, voglio solo avere un singolo giocatore sincronizzato con il server. Teoricamente, ho ipotizzato che un giocatore da solo con la previsione sul lato client non avrebbe richiesto correzioni del server, poiché non ci sono fattori esterni che influenzano il suo movimento. Pertanto, il mio prototipo attualmente ha solo un giocatore sincronizzato con un server senza invio di correzioni del server.
Se hai familiarità con le reti di gioco, penso che potresti saltare le sezioni di contesto, anche se potrei aver fatto qualcosa di sbagliato lungo la strada.
Il ciclo client (una volta per frame, una volta ogni ~ 16.67ms)
Il ciclo client semplificato assomiglia a:
Verificare l'input locale (WASD) e impacchettarli come azioni (ad es
Type=MoveLeft, Time=132.0902, ID=15
.). Conserviamo le azioni in pacchetto per inviarle in seguito. Inoltre, applichiamo direttamente l'azione desiderata alla simulazione fisica locale del gioco. Ad esempio, se abbiamoMoveLeft
un'azione, applichiamo una forza verso sinistra sulla velocità del giocatore.Controlla per inviare azioni. Per evitare di abusare della larghezza di banda del client, inviare le azioni in pacchetti solo a determinati intervalli (ad es. 30ms).
Applica modifiche al server. Ad un certo punto questo gestirà i delta e le correzioni ricevute dal server e li applicherà alla simulazione locale del gioco. Per questa domanda particolare, questo non viene utilizzato.
Aggiorna la fisica locale. Esegui il loop fisico sul giocatore principale. Fondamentalmente, questo fa la previsione sul lato client del movimento del giocatore. Questo aggiunge gravità alla velocità del giocatore, applica la velocità del giocatore alla sua posizione, corregge le collisioni lungo il percorso, ecc. Dovrei specificare che la simulazione fisica viene sempre eseguita con un delta fisso (chiamato più volte a seconda del vero delta secondi) .
Sto saltando alcuni dettagli specifici sulla fisica e altre sezioni perché ritengo che non siano necessari per la domanda, ma mi sento libero di farmi sapere se sarebbero rilevanti per la domanda.
Il loop del server (ogni 15ms)
Il loop del server semplificato è simile a:
Gestire le azioni. Controllare i pacchetti di azioni ricevuti dai client e applicarli alla simulazione fisica del server. Ad esempio, potremmo ricevere 5
MoveLeft
azioni e applicheremo la forza alla velocità 5 volte . È importante notare che un intero pacchetto di azioni viene eseguito su un "frame" , contrariamente al client in cui viene applicato non appena si verifica l'azione.Aggiorna la logica di gioco. Aggiorniamo la fisica del gioco, spostando i giocatori e risolvendo le collisioni, ecc. Inoltre confezioniamo tutti gli eventi importanti che sono stati inviati ai giocatori (ad esempio, la salute di un giocatore è caduta, un giocatore è morto, ecc.) In seguito.
Invia correzioni. Inviamo regolarmente delta (ad es. Una volta ogni 35ms) ad altri giocatori (ad es. Posizioni dei giocatori, salute, ecc.) Se recentemente sono cambiati. Questa parte non è attualmente implementata, poiché desidero che la simulazione di un singolo giocatore dia gli stessi risultati sul client e sul server senza correzioni, per assicurarsi che la previsione sul lato client funzioni correttamente.
Il problema
Il sistema attuale funziona bene in circostanze semplici, e sono stato felicemente sorpreso di vedere che ha dato risultati molto simili con semplici movimenti orizzontali (le imprecisioni sono dovute a errori di precisione in virgola mobile, credo):
Ignora la grafica del prototipo. Rettangolo bianco = giocatore, rettangoli rossi = ostacoli, blu = sfondo
Tuttavia, ricevo errori di sincronizzazione dopo aver fatto movimenti sensibili al tempo, come saltare e avvicinarmi a un ostacolo isolato:
In teoria, mi aspetterei che entrambi finiscano sempre con gli stessi risultati, in quanto non vi sono fattori esterni per il cliente che influenzano la sua posizione. In pratica, tuttavia, penso di capire il problema.
Poiché saltare attorno a un ostacolo del genere dipende molto dalla tempistica del giocatore, piccole variazioni di quando la velocità viene applicata alla posizione avranno ripercussioni sul risultato (ad esempio il cliente potrebbe allontanarsi appena in tempo per evitare una collisione con il ostacolo, mentre il server lo farebbe poiché riceverà in seguito l'intero pacchetto di azioni e rimarrà bloccato sull'ostacolo per un breve periodo di tempo, modificando il risultato finale). La differenza tra il modo in cui il client e il server lo gestiscono è principalmente che il client esegue tutte le sue azioni mentre si verificano, mentre il server le esegue tutte in blocco man mano che le riceve.
La domanda
Questo lungo contesto porta infine alla mia domanda (grazie per aver letto fino a questo punto): è normale richiedere correzioni del server anche quando c'è solo un giocatore sincronizzato con il server, o dovrei usare alcune tecniche per evitare la desincronizzazione in situazioni sensibili al tempo ?
Ho pensato ad alcune possibili soluzioni, alcune delle quali mi sento meno a mio agio:
Implementare la correzione del server. Supponi semplicemente che si tratti di un comportamento normale e di errori corretti nel momento in cui si verificano. Volevo implementarlo comunque, ma volevo solo assicurarmi che ciò che ho fatto finora sia accettabile.
Utilizzare il tempo client fornito per applicare le azioni desiderate. Immagino che questo sarebbe simile alla compensazione del ritardo, che richiede di "tornare indietro nel tempo" e controllare i movimenti. Un po 'come applicare le correzioni del server, tornare indietro nel tempo e riapplicare le azioni successive. Non mi piace l'idea. Sembra complesso, costoso nelle risorse e richiede di fidarsi del tempo dato dal cliente (anche se ho intenzione di verificare davvero che il tempo appaia relativamente legittimo).
Chiedi a GameDevelopment StackExchange un'idea fantastica che risolverà tutti i miei problemi.
Sto appena iniziando nel mondo del gioco in rete, quindi sentiti libero di correggere / criticare / insultare uno qualsiasi dei concetti di cui sopra o dare idee / risorse che potrebbero aiutarmi nel mio viaggio nel meraviglioso mondo del networking. Scusatemi se avessi potuto trovare la mia risposta altrove, non ci sono riuscito.
Grazie mille per il tuo prezioso tempo.