Wie funktioniert die clientseitige Vorhersage?

33

Ich habe Valve + Gafferon und Hunderte von Seiten von Google gelesen, aber aus irgendeinem Grund kann ich mich nicht mit der Kundenvorhersage befassen.

Meines Erachtens ist das Grundproblem:

  • Client A sendet Eingaben an T0
  • Server empfängt Eingaben um T1
  • Alle Kunden erhalten die Änderung um T2

Unter T2Verwendung der Client-Vorhersage befindet sich Client A nun an einer Position, die für geeignet ist T4.

Wie stellen Sie sicher, dass der Client A dem Server nicht voraus ist, wenn er voraussagt, dass der Server die Bewegungsanforderung akzeptiert? Offensichtlich sind sie die ganze Zeit voraus, was dazu führt, dass sie an den Ort zurückkehren, an dem der Server sie zuletzt gesehen hat. Bei allen Korrekturen, die ich versucht habe, ist dies immer noch spürbar, wenn Sie anhalten, da der Server hinter Ihnen anhält

Chris Evans
quelle

Antworten:

35

Ich habe eine Reihe von Artikeln dazu geschrieben. Es basiert auf denselben Ideen, die Sie an anderer Stelle gelesen haben, wird jedoch sehr detailliert und (ich hoffe) verständlich erklärt.

Insbesondere ist der Artikel über die clientseitige Vorhersage dieses .

ggambett
quelle
Ausgezeichnete Artikel :-) Ich würde gerne den vierten Teil der Serie sehen. Als kleiner Vorschlag würde ein Link zum nächsten Teil am Ende jedes Artikels sicherlich die Navigation verbessern.
ODER Mapper
5
@ORMapper - Ich habe endlich den 4. Artikel geschrieben! gabrielgambetta.com/fpm4.html
ggambett
Ein dickes Lob für Ihre Artikelserie :-) Sehr hilfreich, danke :-)
ODER Mapper
Alle Artikel (die ich finden konnte), die sich mit der Rekonstruktion von Vergangenheit unter Verwendung gespeicherter Schnappschüsse befassen, nehmen die Aufnahme als Beispiel. Gilt das auch für Bewegung? Ich kann mir vorstellen, dass Bewegungs-Resimulation bei anderen Spielern zu großen Unterschieden führen kann, wenn sie miteinander kollidieren. Nehmen wir an, zwei Spieler treten gegeneinander an und einer von ihnen hört auf, sich einige "Schritte" vom Kollisionspunkt entfernt zu bewegen. Dieser Stoppbefehl kommt wegen Verzögerung zu spät. Wenn wir also die Welt neu simulieren, wären die beiden Spieler in sehr unterschiedlichen Positionen
Lope
Das ist eine interessante Frage. Leider habe ich keine endgültige Antwort. Ich denke, es hängt davon ab, wie kritisch die Bewegungen für das Spiel sind. triffst du nur jemanden und nichts passiert? In diesem Fall ist es dem Server wahrscheinlich egal, es wird als Vorhersagefehler angesehen (wir haben alle gesehen, dass es an Drosselstellen passiert ist, oder?). Tötest du den anderen Spieler bei Kontakt? In diesem Fall ist es viel wichtiger, es richtig zu machen, und es kann sich lohnen, es erneut zu simulieren. Beachten Sie, dass Sie irgendwann einige Pakete als "zu alt" verwerfen müssen, andernfalls würden Sie zu jeder Zeit möglicherweise von t = 0 aus erneut simulieren.
ggambett
4

Ich habe dies nicht implementiert (es kann also Probleme geben, die ich nicht sofort sehe), aber ich dachte, ich würde versuchen zu helfen.

Folgendes hast du gesagt:

Client A sendet eine Eingabe bei T0

Der Server empfängt Eingaben bei T1

Alle Kunden erhalten die Änderung bei T2

Bei T2 jedoch befindet sich Client A unter Verwendung der Client-Vorhersage an einer Position, die T4 entspricht.

Es wäre wahrscheinlich nützlich, in Bezug auf die Serverzeit zu denken. Es ist (wahrscheinlich) sehr ähnlich wie die Interpolation funktioniert.

Jeder Befehl wird mit einer Serverzeit gesendet. Diese Serverzeit wird zu Beginn eines Matches ermittelt, indem der Server-Tick abgefragt wird, um die Ping-Zeit zu kompensieren. Auf dem Client haben Sie Ihre eigene lokale Tickanzahl und jeder Befehl, den Sie senden, wird in Server-Ticks konvertiert (eine einfache Subtraktionsoperation).

Außerdem rendert der Client immer "in der Vergangenheit". Sie gehen also davon aus, dass die Welt, die der Client sieht, beispielsweise 100 ms hinter der Zeit des Servers liegt.

Formulieren wir also Ihr Beispiel mit der Serverzeit (mit S bezeichnet).

Der Client sendet eine Eingabe bei T0 mit der Serverzeit S0 (was meiner Meinung nach wirklich "Client-Darstellung der Serverzeit minus Interpolationszeit" ist). Der Client wartet nicht auf die Antwort vom Server und wechselt sofort.

Der Server empfängt Eingaben bei T1. Server ermittelt die maßgebliche Position des Clients zur Serverzeit S0, die vom Client angegeben wird. Sendet das an den Kunden.

Der Client erhält die maßgebliche Position bei T2 (noch mit Angabe der Serverzeit S0). Der Client protokolliert vergangene Ereignisse (wahrscheinlich nur eine Warteschlange aller unbestätigten Vorhersagen).

Wenn sich die vorhergesagte Position / Geschwindigkeit / was auch immer der Server an S0 zurücksendet von dem unterscheidet, was der Client an S0 gespeichert hat, handhabt der Client dies irgendwie. Entweder, indem Sie den Player auf die vorherige Position zurücksetzen oder die vorherige Eingabe erneut simulieren, oder vielleicht etwas anderes, woran ich nicht gedacht habe.

Tetrade
quelle
3
Das ist alles in Ordnung, mit Ausnahme der Tatsache, dass der Client in der Vergangenheit gerendert hat. Relativ zum Server rendert der Client tatsächlich in der Zukunft! Der Server weiß, dass die Informationen, die er von jedem Client hat, alt sind und dass sich jeder Client seitdem bereits geändert hat.
Kylotan
2

Tatsächlich gibt es eine Open-Source-Implementierung in Github, die zeigt, wie das gemacht wird. Schauen Sie sich Lance.gg an

github repo: https://github.com/lance-gg/lance

Der Client-Vorhersagecode ist in dem aufgerufenen Modul implementiert src/syncStrategies/ExtrapolateStrategy.js

Neben der Extrapolation gibt es zwei Konzepte, die ich oben nicht erwähnt habe:

  1. Inkrementelles Biegen. Anstatt die Serverkorrektur auf einmal anzuwenden, lassen Sie das Delta grundsätzlich in kleinen Schritten anwenden. Auf diese Weise passen entfernte Objekte ihre Positionen schrittweise an die Serverpositionen an. Es gibt Positionsbiegung, Geschwindigkeitsbiegung, Winkelbiegung und Winkelgeschwindigkeitsbiegung. Möglicherweise möchten Sie auch unterschiedliche Biegefaktoren für unterschiedliche Objekte.
  2. Step Re-Enactment. Die Tatsache, dass die Daten in der Vergangenheit liegen, bedeutet, dass Sie die Zeit auf die Serverdatenzeit zurücksetzen und ab diesem Zeitpunkt neu starten können. Natürlich müssen Sie sich immer noch in Richtung der neu gefundenen Position beugen, anstatt dorthin zu springen.
Gary Weiss
quelle
1

Client A ist dem Server immer voraus - aber das spielt keine Rolle. Sie müssen den Client nur zurücksetzen, wenn der Server angibt, dass ein Problem mit der gemeldeten Position vorliegt. Zu diesem Zeitpunkt führt der Client alle Änderungen, die er seit dem Fehler mit den korrigierten Werten vorgenommen hat, erneut aus, um ihn in einen kompatiblen Zustand zu versetzen mit dem Server.

Zu diesem Zweck muss sich der Client einen Teil seines früheren Status und vergangener Aktualisierungen merken. Dies sind möglicherweise nur einige einfache Werte wie Position, Geschwindigkeit, Ausrichtung und dergleichen. Der Server sendet in regelmäßigen Abständen eine Bestätigung, dass verschiedene Client-Updates legitim waren, dh, sie können jetzt vom Client vergessen werden. Wenn der Server jedoch meldet, dass eine Aktualisierung ungültig war, wird der Clientstatus auf diesen Punkt zurückgesetzt und die zukünftigen Änderungen werden auf diesen geänderten Status angewendet.

Es gibt einige zusätzliche Links am Ende des Valve-Artikels, die es wert sind, gelesen zu werden. Dies ist einer von ihnen: https://developer.valvesoftware.com/wiki/Prediction

Kylotan
quelle
Habe ich also Recht, wenn ich denke, dass client (at t=4) Informationen über empfängt t=2, also den Status zurücksetzt, um t=2dann Aktualisierungen erneut auszuführen, um Objekte von t=2nach zu bringen t=4?
George Duckett
Ich verstehe es immer noch nicht aus irgendeinem Grund. Dem Server wird nicht die Position des Players mitgeteilt, sondern nur die Eingaben. Der Spieler bewegt sich also von der letzten Position, an der er sich befunden hat. Die Eingabe wird angewendet. Server ist informiert. Der Server bestätigt die Eingabe an alle. Unter der Annahme, dass alle Befehle akzeptiert werden, befindet sich der Server weiterhin hinter Client A. Wenn Client A beendet wird, stoppt sein Charakter sofort und gleitet zum Serverstandort zurück, wenn er die Bestätigung zum Beenden erhält.
Chris Evans
@GeorgeDuckett: Ja (obwohl es nicht t = 4 sein muss, könnte es sein, wann immer eine Diskrepanz erkannt wird und es könnte eine beliebige Anzahl von erneut angewendeten Updates geben.)
Kylotan
@ChrisEvans: Bekannter Status + Änderungen basierend auf der Eingabe entsprechen sowieso dem Sendestatus. Das Stopp-Beispiel ist an sich eine Eingabe, und der Server simuliert weiterhin Bewegungen, bis er diese Eingabe empfängt. Unter der Annahme einer konstanten Latenz hält der Server den Spieler an genau der Position an, die der Client sah, als er aufhörte sich zu bewegen, weil der Client dem Server voraus war. (In der realen Welt variiert die Latenz, daher interpolieren Sie ein wenig, um sie
auszugleichen