Ich schreibe ein Spiel, das viele zeitbasierte Aspekte hat. Ich benutze Zeit, um Spielerpositionen zu schätzen, wenn das Netzwerk blockiert und Pakete nicht durchlaufen werden (und die Zeit zwischen dem Empfang von Paketen und nicht). Es ist ein Pacman-Spiel in dem Sinne, dass ein Spieler eine Richtung wählt und nicht aufhören kann, sich zu bewegen, so dass dieses System Sinn macht (oder zumindest denke ich, dass es das tut).
Ich habe also zwei Fragen: 1) Wie synchronisiere ich die Uhren der Spiele zu Beginn, da es im Netzwerk zu Verzögerungen kommt? 2) Ist es in Ordnung, sie NICHT zu synchronisieren und einfach anzunehmen, dass sie gleich sind (mein Code ist zeitzonenunabhängig). Es ist kein super wettbewerbsfähiges Spiel, bei dem die Leute ihre Uhren ändern würden, um zu betrügen, aber trotzdem.
Das Spiel wird in Java und Python programmiert (parallele Entwicklung als Projekt)
Antworten:
Ich denke, es ist definitiv nicht in Ordnung, die Uhr im System zu synchronisieren . Der Benutzer erwartet nicht, dass Sie die Systemeinstellungen berühren, und viele Systeme lassen dies nicht einmal zu.
Alles, was Sie brauchen, ist eine Korrelation, um den Zeitstempel von der Uhr einer Seite in die Uhr der anderen Seite umzuwandeln. Andererseits muss diese Korrelation ziemlich genau sein, etwa bis zu einer Hundertstelsekunde, wenn Sie sie zur Vorhersage der Spielerpositionen verwenden möchten. Die Systemuhr wird niemals so gut zwischen zufälligen Maschinen korrelieren. Daher sollten Sie die Korrelation selbst herstellen und dabei einige Variationen des NTP- Themas verwenden, die wahrscheinlich in Ihre anderen Nachrichten eingebettet sind, um die Netzwerkbandbreite zu schonen.
Die Grundidee könnte sein, dass Sie mit jedem Paket, das Sie gesendet haben, den Zeitstempel gesendet haben und die Sequenznummer und den Zeitstempel, als Sie das letzte Paket von der anderen Seite empfangen haben. Daraus berechnen Sie den Roundtrip: Wenn beispielsweise Paket Q angibt, dass es um 1000 gesendet wurde und Paket P mit 500 empfangen wurde, als wenn Sie Paket P mit 0 gesendet haben und Q mit 800 empfangen, beträgt der Roundtrip (800 - 0) ) - (1000 - 500) = 300. Es gibt keine Möglichkeit, die Assymetrie zu kennen. Sie nehmen also einfach an, dass das Paket die Hälfte (150) Ticks in beide Richtungen benötigt. Und dieser entfernte Zeitstempel liegt um 1000 - (800 - 150) = 350 Ticks vor dem lokalen. Die Hin- und Rückfahrt variiert. Wenn Sie davon ausgehen, dass die Uhr ziemlich genau ist, sollten Sie einen langfristigen Durchschnitt der Korrelation verwenden.
Beachten Sie, dass Sie die Systemuhr auch nicht für die Uhr verwenden möchten. Sie werden möglicherweise auf halbem Weg neu synchronisiert, was Sie aus der Bahn wirft. Sie sollten
clock(CLOCK_MONOTONIC)
unter Unix oderGetTickCount
Windows verwenden (nicht sicher, wie diese APIs derzeit in Java oder Python eingeschlossen sind).Hinweis: Die
SO_TIMESTAMP
Socket-Option (siehe Socket (7) , der von ott-- im Kommentar zur Frage erwähnt wird) ist nützlich, um den Effekt der Latenz der Ereignisschleife, die die Pakete empfängt, herauszufiltern. Ob sich die Mühe lohnt, hängt davon ab, wie genau Sie sind.quelle
Woher weißt du, welche Uhr des Spielers korrekt ist? Verwenden Sie keine Referenzuhr .
NTP ist hier übertrieben - Sie benötigen nur eine Genauigkeit von ~ 1 Sekunde - verwenden Sie also rdate oder wählen Sie etwas aus einem der vielen Taktsynchronisationsalgorithmen aus.
Wenn Sie eine Methode ausgewählt haben, lassen Sie den Computer jedes Spielers die Zeit nach dieser Methode erfassen (ohne die Systemuhr zu ändern). Was auch immer der Unterschied zwischen der Referenz-UTC-Zeit und der Systemuhr-UTC-Zeit der Spieler ist, ist ihr effektiver Versatz. Jedes Mal, wenn Sie zeitbezogene Berechnungen durchführen, um beispielsweise Bot-Bewegungen oder Ray-Trace-Aufzählungszeichen zu extrapolieren, berücksichtigen Sie diesen Versatz, nachdem Sie die Systemzeit erhalten haben. Durch die Verwendung von UTC werden Zeitzonenfaktoren eliminiert.
quelle
Ich stimme den Aussagen zu, dass Sie dafür kein NTP verwenden oder sich der Systemuhr nähern sollten. Wenn Sie diese Anforderung tatsächlich untersuchen, werden Sie feststellen, dass Sie die folgenden Anforderungen haben:
Dies ist eine vereinfachte Übersicht - ich versuche nicht, Probleme wie Latenz / verworfene Pakete / usw. zu behandeln -, aber es ist das Grundgerüst, auf dem das Ganze basieren sollte.
Keiner dieser Bedürfnisse in der Nähe der Systemuhr gehen oder sich mit Fragen wie unterschiedliche Zeitzonen betroffen sein, auch wenn das letzte Element kann eine Zeitzone verwenden , falls gewünscht. Wichtig ist, dass die tatsächlich verstrichenen Zeiten mit einem hochauflösenden Timer auf Nullbasis gemessen werden, sodass sie völlig unabhängig von Zeitzonendifferenzen sind. Möchten Sie die aktuelle Uhrzeit auf dem Server ermitteln? Fügen Sie einfach die verstrichene Zeit zur Referenzbasiszeit hinzu und Sie haben sie. Ebenso für den Kunden.
quelle