Come sincronizzare gli orologi in rete per lo sviluppo di giochi?


10

Sto scrivendo un gioco che ha molti aspetti basati sul tempo. Uso il tempo per stimare le posizioni dei giocatori quando le bancarelle e i pacchetti di rete non stanno attraversando (e il tempo che intercorre tra la ricezione dei pacchetti e non). È 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 penso che lo faccia).

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

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


7
look up ntp
ratchet freak

5
Sono sicuro che questa domanda è già coperta su gamedev.stackexchange.com, o almeno appartiene a questo.
congusbongus,

1
@CongXu: non ne sono così sicuro. Mentre questo è un compito svolto normalmente per i giochi, non è intrinsecamente specifico per lo sviluppo del gioco. Molti altri sistemi distribuiti richiedono un orologio sincronizzato.
Jan Hudec,

2
Hai già provato a utilizzare l'opzione IPv4 TIMESTAMP? Maggiori informazioni sono disponibili su linux.die.net/man/7/socket da lì a linux.die.net/man/3/cmsg e quindi un piccolo programma di esempio su pdbuchan.com/rawsock/rawsock.html l'ultimo prima del Sezione IPv6.
ott--

2
I giochi (applicazioni) non devono toccare l'orologio di sistema.
Ripristina Monica - M. Schröder il

Risposte:


9

Penso che sia sicuramente non è OK per Synchornize l'orologio del sistema . L'utente non si aspetta che tu tocchi le impostazioni di sistema e molti sistemi non te lo permetteranno nemmeno.

Tutto ciò che serve è avere una correlazione per convertire il timestamp dall'orologio di un lato all'orologio dell'altro lato. D'altra parte è necessario che questa correlazione sia piuttosto precisa, diciamo almeno al centesimo di secondo, se si desidera utilizzarla per prevedere 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 alcune variazioni sul tema NTP , probabilmente incorporato negli altri tuoi messaggi per preservare la larghezza di banda della rete.

L'idea di base potrebbe essere che con ogni pacchetto che hai inviato il timestamp lo hai inviato e il numero di sequenza e il timestamp quando hai ricevuto l'ultimo pacchetto dall'altra parte. Da questo si calcola il viaggio di andata e ritorno: ad esempio se il pacchetto Q dice che è stato inviato a 1000 e il pacchetto P è stato ricevuto a 500, rispetto a quando si è inviato il pacchetto P a 0 e si riceve Q a 800, il viaggio di andata e ritorno è (800 - 0 ) - (1000 - 500) = 300. Non è possibile conoscere l'assimetria, quindi si presuppone che il pacchetto richieda metà (150) tick in entrambe le direzioni. E quel timestamp remoto è davanti al locale di 1000 - (800 - 150) = 350 tick. Il viaggio di andata e ritorno varierà. Se si assume che l'orologio sia ragionevolmente preciso, è necessario utilizzare una media a lungo termine della correlazione.

Si noti che non si desidera utilizzare nemmeno l'orologio di sistema per l'orologio. Possono risincronizzarsi a metà strada, gettandoti fuori pista. Dovresti usarlo clock(CLOCK_MONOTONIC)su Unix o GetTickCountsu Windows (non sei sicuro di come queste API siano avvolte in Java o Python in questo momento).


Nota: l' SO_TIMESTAMPopzione socket (vedi socket (7) menzionata da ott-- in commento alla domanda) sarebbe utile per separare l'effetto della latenza del loop di eventi che riceve i pacchetti. Se ne valga la pena dipende da quanta buona precisione hai bisogno.


1

Come fai a sapere quale orologio del giocatore è corretto? No, quindi usa un orologio di riferimento .

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

Uno hai scelto un metodo, fai in modo che la macchina di ogni giocatore raccolga il tempo per quel metodo (senza cambiare il suo orologio di sistema). Qualunque differenza ci sia tra l'ora UTC di riferimento e l'ora UTC dell'orologio di sistema dei giocatori è il loro offset effettivo. Ogni volta che si eseguono calcoli relativi al tempo, ad esempio per estrapolare movimenti di bot o proiettili ray-trace, si tiene conto di questo offset dopo aver ottenuto l'ora di sistema. L'uso di UTC eliminerà i fattori del fuso orario.


1

Secondo affermazioni che non dovresti usare NTP o avvicinarti all'orologio di sistema per questo. Se esamini effettivamente questo requisito, scoprirai di avere le seguenti esigenze:

  • Quanto tempo è trascorso dal fotogramma precedente in modo da poter avanzare qualsiasi elemento basato sul tempo. Questo può essere diverso su client e server se entrambi spuntano a velocità diverse (ad es. A volte potresti vedere server che funzionano a 20Hz fissi (o qualsiasi altra cosa) ma client che possono funzionare alla velocità che desiderano).
  • Quanto tempo è trascorso dall'avvio della mappa corrente. Questo è un timer a base zero (basta avviarlo su 0 sia sul client che sul server all'avvio) e l'ora del server è considerata il "master", quindi il server invia la vista corrente di questo tempo al client per ogni frame che gira sul server. Ciò può essere ottenuto prendendo l'ora del server corrente e sottraendo l'ora in cui è stato avviato il server o accumulando i tempi per fotogramma sopra indicati. Il tempo per fotogramma lato client sopra riportato può anche essere utilizzato per generare punti di interpolazione tra due frame server consecutivi.
  • Un "tempo base" di riferimento dal quale avanza tutto il tempo; questo può essere (ma non è assolutamente necessario che sia per tutti i tipi di gioco) uguale su client e server e viene inizializzato all'inizio del gioco (o sulla mappa corrente) ma mai modificato dopo (a meno che un nuovo gioco - o una nuova mappa - è avviato).

Questo è uno schema semplificato - non tento di affrontare questioni come la latenza / i pacchetti rilasciati / ecc. - ma è il framework di base su cui dovrebbe basarsi il tutto.

Niente di tutto ciò deve avvicinarsi all'orologio di sistema o occuparsi di questioni come fusi orari diversi, anche se l'ultimo elemento può utilizzare un fuso orario, se lo si desidera. L'importante è che i tempi effettivi trascorsi siano misurati utilizzando un timer a base zero ad alta risoluzione, quindi sono completamente indipendenti dalle differenze di fuso orario. Vuoi trovare l'ora corrente sul server? Basta aggiungere il tempo trascorso al tempo base di riferimento e il gioco è fatto. Allo stesso modo per il cliente.

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.