Come sincronizzare gli orologi sulla rete per lo sviluppo del gioco?

10

Sto scrivendo un gioco che ha molti aspetti basati sul tempo. Uso il tempo per valutare le posizioni dei giocatori quando la rete si blocca e i pacchetti non stanno attraversando (e il tempo che intercorre tra la ricezione e non il pacchetto). È un gioco di tipo pacman nel senso che un giocatore sceglie una direzione e non può smettere di muoversi, quindi quel sistema ha senso (o almeno credo che lo faccia).

Quindi ho due domande: 1) Come faccio a sincronizzare gli orologi dei giochi all'inizio poiché c'è un ritardo nella rete. 2) Va bene NON sincronizzarli e presumere semplicemente che siano uguali (il mio codice è indipendente dal fuso orario). Non è un gioco super competitivo in cui le persone cambieranno i loro orologi per imbrogliare, ma ancora.

Il gioco è in programmazione in Java e Python (sviluppo parallelo come progetto)

    
posta sinθ 17.06.2013 - 01:48
fonte

3 risposte

9

Penso che sia not OK a sincronizzare l'orologio nel sistema . L'utente non si aspetta che tu tocchi le impostazioni di sistema e molti sistemi non ti permetteranno nemmeno di farlo.

Tutto ciò che serve è avere una correlazione per convertire il timestamp dall'orologio di un lato all'altro dell'orologio del lato opposto. D'altra parte hai bisogno che questa correlazione sia piuttosto precisa, diciamo almeno al centesimo di secondo, se vuoi usarla per predire le posizioni dei giocatori. L'orologio di sistema non sarà mai così ben correlato tra macchine casuali. Quindi dovresti stabilire tu stesso la correlazione, usando qualche variazione sul tema NTP , probabilmente incorporato negli altri tuoi messaggi per conservare la larghezza di banda della rete .

L'idea di base potrebbe essere che con ogni pacchetto che hai inviato il timestamp che hai inviato e il numero di sequenza di e timestamp quando hai ricevuto l'ultimo pacchetto dall'altra parte. Da questo si calcola il viaggio di andata: per esempio se il pacchetto Q dice che è stato inviato a 1000 e il pacchetto P è stato ricevuto a 500, rispetto a quando hai inviato il pacchetto P a 0 e stai ricevendo Q a 800, il round-trip è (800 - 0) - (1000 - 500) = 300 Non c'è modo di conoscere l'asimmetria, quindi presumi che il pacchetto impieghi metà (150) zecche in entrambe le direzioni. E questo timestamp remoto è più veloce del locale di 1000 - (800 - 150) = 350 tick. Il viaggio di andata e ritorno varierà. Se ritieni che l'orologio sia ragionevolmente preciso, dovresti utilizzare una media a lungo termine della correlazione.

Nota che non vuoi nemmeno usare l'orologio di sistema per l'orologio. Potrebbero essere risincronizzati a metà strada, gettandoti fuori pista. Dovresti usare clock(CLOCK_MONOTONIC) su Unix o GetTickCount su Windows (non sono sicuro di come queste API siano avvolte in Java o Python in questo momento).

Nota: l'opzione SO_TIMESTAMP socket (vedi socket (7) menzionata da ott-- nel commento sulla domanda) sarebbe utile per separare l'effetto della latenza del ciclo di eventi che riceve i pacchetti. Se vale la pena, lo sforzo dipende dalla precisione di cui hai bisogno.

    
risposta data 17.06.2013 - 11:41
fonte
1

Come fai a sapere quale orologio del giocatore è corretto? Non lo fai, quindi utilizza un clock di riferimento .

NTP è eccessivo qui - hai solo bisogno di ~ 1 secondo di precisione - quindi usa rdate o scegli qualcosa da uno dei tanti algoritmi di sincronizzazione dell'orologio.

Se hai scelto un metodo, prendi la macchina di ogni giocatore per prendere il tempo per quel metodo (senza cambiare il loro orologio di sistema). Qualunque sia la differenza tra l'ora UTC di riferimento e l'ora UTC dell'orologio di sistema dei giocatori è il loro offset effettivo. Ogni volta che esegui calcoli correlati al tempo, ad es. estrapola i movimenti del bot o i proiettili di ray-trace, calcoli questo offset dopo aver ottenuto il tempo di sistema. L'uso di UTC eliminerà i fattori del fuso orario.

    
risposta data 18.06.2013 - 17:03
fonte
1

Le seconde affermazioni che non dovresti usare NTP o andare vicino all'orologio di sistema per questo. Se effettivamente esamini questo requisito, scoprirai che hai le seguenti necessità:

  • Quanto tempo è trascorso dal frame precedente in modo da poter avanzare in qualsiasi momento. Questo può essere diverso su client e server se entrambi spuntano a velocità diverse (ad esempio potresti talvolta vedere server che funzionano a 20 Hz fissi (o qualsiasi altra cosa) ma i client che sono autorizzati a girare quanto vogliono).
  • Quanto tempo è trascorso dall'avvio della mappa corrente. Questo è un timer a base zero (basta avviarlo a 0 sia sul client che sul server all'avvio) e l'ora del server è considerata "master", quindi il server invia la vista corrente di questo momento al client per ogni frame che gira sul server. Questo può essere ottenuto prendendo l'ora del server corrente e sottraendo l'ora in cui il server è partito, o accumulando le volte per frame sopra. Il tempo per-frame precedente al lato client può anche essere utilizzato per generare punti di interpolazione tra due frame di server consecutivi.
  • Un riferimento "tempo base" dal quale avanzano tutti gli altri tempi; questo può essere (ma non è assolutamente necessario per tutti i tipi di gioco) lo stesso su entrambi i client e server e viene inizializzato all'inizio del gioco (o mappa corrente) ma non è mai cambiato dopo (a meno un nuovo gioco - o una nuova mappa - è stato avviato).

Questo è uno schema semplificato: non cerco di affrontare problemi come latenza / pacchetti scartati / ecc., ma è il framework di base su cui basare il tutto.

Nessuno di questi deve avvicinarsi all'orologio del sistema o preoccuparsi di questioni come fusi orari diversi, sebbene l'ultimo elemento possa utilizzare un fuso orario, se lo si desidera. La cosa importante è che i tempi effettivi vengono misurati usando un timer a base zero ad alta risoluzione, quindi sono completamente agnostici rispetto alle differenze di fuso orario. Vuoi trovare l'ora attuale sul server? Basta aggiungere il tempo trascorso al suo tempo base di riferimento e ce l'hai. Allo stesso modo per il cliente.

    
risposta data 18.06.2013 - 18:18
fonte

Leggi altre domande sui tag