Ich arbeite an einem 2D-Top-Down-Shooter und gebe mein Bestes, um Konzepte zu kopieren, die in vernetzten Spielen wie Quake 3 verwendet werden.
- Ich habe einen autorisierenden Server.
- Der Server sendet Snapshots an Clients.
- Schnappschüsse enthalten einen Zeitstempel und Entitätspositionen.
- Objekte werden zwischen Schnappschusspositionen interpoliert, damit die Bewegung reibungslos aussieht.
- Die Interpolation von Entitäten erfolgt zwangsläufig geringfügig "in der Vergangenheit", sodass wir mehrere Schnappschüsse haben, zwischen denen interpoliert werden kann.
Das Problem, dem ich gegenüberstehe, ist "Uhrzeitsynchronisation".
- Nehmen wir der Einfachheit halber einmal an, dass es beim Übertragen von Paketen zum und vom Server keine Latenz gibt.
- Wenn die Serveruhr 60 Sekunden vor der Clientuhr liegt, liegt ein Snapshot-Zeitstempel 60000 ms vor dem lokalen Client-Zeitstempel.
- Daher werden Entitäts-Snapshots gesammelt und etwa 60 Sekunden lang gespeichert, bevor der Client erkennt, dass eine bestimmte Entität seine Züge ausführt, da es so lange dauert, bis die Client-Uhr aufholt.
Ich habe es geschafft, dies zu überwinden, indem ich bei jedem Empfang eines Snapshots die Differenz zwischen Server- und Client-Uhr berechnet habe.
// For simplicity, don't worry about latency for now...
client_server_clock_delta = snapshot.server_timestamp - client_timestamp;
Wenn ich feststelle, wie weit die Entität in der Interpolation ist, addiere ich einfach die Differenz zur aktuellen Zeit des Kunden. Das Problem dabei ist jedoch, dass es zu Ruckeln kommt, da die Differenz zwischen den beiden Uhren abrupt schwankt, da Schnappschüsse schneller / langsamer als andere ankommen.
Wie kann ich die Uhren genau genug synchronisieren, dass die einzige wahrnehmbare Verzögerung die ist, die für die Interpolation fest codiert ist, und die, die durch gewöhnliche Netzwerklatenz verursacht wird?
Mit anderen Worten, wie kann ich verhindern, dass die Interpolation zu spät oder zu früh startet, wenn die Uhren erheblich desynchronisiert sind, ohne dass es zu Ruckeln kommt?
Bearbeiten: Laut Wikipedia kann NTP verwendet werden, um Uhren über das Internet innerhalb weniger Millisekunden zu synchronisieren. Allerdings scheint das Protokoll kompliziert und vielleicht übertrieben für den Einsatz in Spielen?
Antworten:
Nach dem Durchsuchen scheint es keine triviale Aufgabe zu sein, die Uhren von zwei oder mehr Computern zu synchronisieren. Ein Protokoll wie NTP macht einen guten Job, ist aber angeblich langsam und zu komplex, um in Spielen praktisch zu sein. Außerdem wird UDP verwendet, was bei mir nicht funktioniert, da ich mit Web-Sockets arbeite, die UDP nicht unterstützen.
Ich habe hier jedoch eine Methode gefunden , die relativ einfach zu sein scheint:
Es wird behauptet, dass die Uhren innerhalb von 150 ms (oder besser) voneinander synchronisiert werden.
Ich weiß nicht, ob das für meine Zwecke gut genug ist, aber ich konnte keine genauere Alternative finden.
Hier ist der Algorithmus, den es bereitstellt:
Diese Lösung scheint meine Frage zufriedenstellend zu beantworten, da sie die Uhr synchronisiert und dann stoppt, sodass die Zeit linear fließen kann. Während meine anfängliche Methode die Uhr ständig aktualisiert, springt die Zeit beim Empfang von Schnappschüssen etwas umher.
quelle
Grundsätzlich kann man nicht die ganze Welt reparieren und irgendwann muss man die Grenze ziehen.
Wenn der Server und alle Clients die gleiche Bildrate verwenden, müssen sie nur beim Herstellen einer Verbindung und gelegentlich danach, insbesondere nach einem Latenzereignis, synchronisieren. Die Latenz beeinflusst weder den Zeitfluss noch die Fähigkeit des PCs, ihn zu messen. In vielen Fällen müssen Sie also hochrechnen, anstatt zu interpolieren. Dies erzeugt ebenso unerwünschte Effekte, aber es ist wieder das, was es ist, und Sie müssen das am wenigsten verfügbare Übel auswählen.
Bedenken Sie, dass in vielen populären MMOs nacheilende Spieler visuell offensichtlich sind. Wenn Sie sehen, wie sie direkt in eine Wand rennen, wird dies von Ihrem Kunden extrapoliert. Wenn Ihr Kunde die neuen Daten erhält, hat der Spieler (auf seinem Kunden) möglicherweise eine beträchtliche Entfernung zurückgelegt und wird an einen neuen Ort teleportieren (das von Ihnen erwähnte "Ruckeln"?). Dies passiert sogar in großen Spielen von bekannten Marken.
Technisch ist dies ein Problem mit der Netzwerkinfrastruktur des Spielers, nicht mit Ihrem Spiel. Der Punkt, an dem es von einem zum anderen geht, ist genau die Linie, die Sie zeichnen müssen. Ihr Code sollte auf 3 verschiedenen Computern ungefähr dieselbe Zeitspanne aufzeichnen. Wenn Sie kein Update erhalten, sollte sich dies nicht auf die Framerate von Update () auswirken. Wenn überhaupt, sollte es schneller sein, da wahrscheinlich weniger zu aktualisieren ist.
"Wenn Sie schlechtes Internet haben, können Sie dieses Spiel nicht wettbewerbsfähig spielen."
Das ist kein Reinfall oder Fehler.
quelle