Holen Sie sich das richtige Timing mit clientseitiger Vorhersage

7

Ich glaube, ich habe mich mit CSP beschäftigt, nachdem ich Gabriel Gambettas Blog, Valve-Artikel und buildnewgames.com gelesen habe, aber ein Problem damit habe, die zeitliche Ausführung von allem zu verstehen.

Wenn ein Spieler die rechte Pfeiltaste gedrückt hält. Ich bewege das Sprite um (Geschwindigkeit * DeltaTime), wobei DeltaTime die Zeit zwischen Frames ist, sodass die Geschwindigkeit bei unterschiedlichen Frameraten gleich ist.

Meine Fragen sind:

  1. Sende ich einen Befehl, um jeden Frame nach rechts zu bewegen?
  2. Wie berechnet der Server diese Bewegung korrekt, da er die deltaTime des Clients nicht kennt?

Schätzen Sie wirklich eine Anleitung zu diesem Thema. Ich verwende HTML5, Javascript, node.js mit socket.io.

Dolyth
quelle
Hallo. Wenn Sie zwei Fragen haben, stellen Sie zwei separate Fragen.
Sean Middleditch

Antworten:

4

Verwenden Sie zum Starten einen festen Zeitschritt. Korrigieren Sie Ihren Zeitschritt

Der Server / Client muss die RTT (Roundtrip-Zeit) der Verbindung schätzen, um die Zeiten zu korrigieren. Der Server empfängt Befehle aus der (jüngsten) Vergangenheit. Die Simulation muss dies berücksichtigen. Es weiß, wo der Kunde war und wohin er ziehen wollte, nicht wohin der Kunde ist und wohin er ziehen möchte. Der Server muss unterschiedliche Clients berücksichtigen, die möglicherweise sehr unterschiedliche RTTs haben.

Im Allgemeinen benötigt der Server genügend Informationen, um zu wissen, wo sich ein Client vor X Millisekunden befand, um Aufzählungskollisionen und dergleichen herauszufinden.

Vernetzung ist schwer. Eine Menge von Multiplayer - Bastler / Indie / Student Spiele ignorieren die meisten der RTT Probleme , indem sie behaupten nur LAN - Spiele verdrahtet zu unterstützen, wo Latenzen sind klein genug für die meisten Spiele zu ignorieren. Wireless und das Internet zwingen Sie dazu, mit variablen, großen Latenzen umzugehen, die Sie umgehen müssen, um in einem Actionspiel zufriedenstellend zu spielen.

Der Artikel über Ventile behandelt dies etwas ausführlicher. Ignorieren Sie ihre Ratschläge zu Rahmenzeiten. es ist lächerlich.

Sean Middleditch
quelle
Danke dafür, das macht Sinn. Es gibt einige widersprüchliche Methoden, um Dinge zu tun, die das Problem verwirren. Ich werde weiterpflügen, das harte Zeug fühlt sich gut an, wenn du es einmal im Kopf hast!
Dolyth
Ihre Aufgabe als Programmierer ist es, die Methode zu finden, die für Ihr Spiel am besten geeignet ist. Das ist der Grund, warum Game-Net-Codierer sehr gefragt sind und viel bezahlt werden - es ist ein harter Job, mehr als viele andere Teile der Spielprogrammierung, die roter sind. Im Allgemeinen gibt es keine vorgefertigten Lösungen für die Probleme, auf die Sie stoßen.
Sean Middleditch
8

Sende ich einen Befehl, um jeden Frame nach rechts zu bewegen?

Sicher. Warum nicht? Solange sich der Spieler nach rechts bewegt, natürlich. Wenn das den Server zu sehr spammt, können Sie natürlich einfach den Befehl senden, sich nach rechts zu bewegen, und den Befehl, sich nicht mehr nach rechts zu bewegen. Sie riskieren jedoch ein problematisches Verhalten, wenn Sie den Befehl "Bewegen stoppen" verpassen. Sie könnten Kompromisse zwischen diesen beiden Ansätzen eingehen. Senden Sie den Befehl, um sich regelmäßig nach rechts zu bewegen, und senden Sie den Stoppbefehl. Lassen Sie den Server so lange in Bewegung bleiben, wie er kürzlich den Befehl erhalten hat, und halten Sie an, wenn Sie aufgefordert werden, anzuhalten, ODER wenn er seit einiger Zeit keine Bewegung mehr erhalten hat.

Wie berechnet der Server diese Bewegung korrekt, da er die deltaTime des Clients nicht kennt?

Der Server sollte sich nicht um die interne Delta-Framerate des Clients kümmern. Es sollte sich um die Zeit kümmern, zu der ein Befehl an ihn gesendet wird. Wenn Ihr Spiel ausreichend deterministisch ist, um eine clientseitige Vorhersage zu ermöglichen, sollten die relativen Frameraten keine Rolle spielen. Um deterministisch zu sein, müsste der Server beispielsweise wissen, wie schnell dieses Zeichen ist. Folgendes meine ich:

Die Idee ist, dass der Server eine eigene Deltazeit hat. Hier ist ein Beispiel, bei dem Minuten anstelle von Millisekunden verwendet werden, um das Konzept klarer zu gestalten. Angenommen, ich soll 60 Meilen und eine Stunde fahren. Das ist das Gleiche wie 1 Meile pro Minute. Nehmen wir an, wir haben das Auto basierend auf einer verstrichenen Zeit bewegt, die variiert. So könnten wir so etwas bekommen:

  • 10 Minuten. (Multiplizieren Sie 10 (Minuten) mit 1 (Meile), um das Auto 10 zu bewegen.)

  • 8 Minuten. (Weitere 8 Minuten sind vergangen, also bewegen wir das Auto 8).

  • 12 Minuten. (12 Minuten * 1 Meile, weitere 12 hinzufügen).

Unsere Summe beträgt also 30 Meilen. Auf der Serverseite wird möglicherweise nicht zur gleichen Zeit abgefragt, aber das Auto wird um den gleichen Betrag bewegt, wenn die Geschwindigkeit immer mit dem Delta multipliziert wird. Angenommen, der Server wird nur alle 15 Minuten abgefragt:

  • 15 Minuten (Multiplizieren Sie 15 (Minuten) mit 1 (Meile) und wir sind bei 15.)
  • 15 Minuten (mach es nochmal, wir sind um 30)

Sowohl der Server als auch der Client wissen, dass sich das Auto 30 Meilen bewegt hat, obwohl sie die verschiedenen Delta-Frameraten des anderen nicht kennen (und sie müssen es nicht wissen). Hoffe, dieses Beispiel hat Sinn gemacht.

Umsetzungsstrategie

Basierend auf den Kommentaren unten möchte ich die folgende Strategie vorschlagen, um die clientseitige Vorhersage zu implementieren: Beginnen Sie damit, keine zu haben. Lassen Sie den Server damit umgehen, wo sich der Player befindet. Senden Sie Ihre Befehle, rechts links usw., lassen Sie den Server die Position berechnen und den Server dann mit dem neuen Standort des Spielers antworten. Verwenden Sie auf der Clientseite den Player-Standort, um den Standort des Players festzulegen. Dies wird funktionieren, aber es wird eine Verzögerung erzeugen, die Sie nicht mögen werden. Versuchen Sie nun, eine clientseitige Vorhersage durchzuführen. Aktualisieren Sie die Client-Position an der Stelle, an der sich der Player Ihrer Meinung nach befinden sollte, bevor er vom Server eine Antwort erhält. Wenn der Server den tatsächlichen Standort hört, aktualisieren Sie den Player so, dass er sich tatsächlich an diesem Standort befindet (dh lassen Sie den Server "gewinnen", wenn er nicht einverstanden ist).

Kurz gesagt, im Moment deuten einige Ihrer Fragen darauf hin, dass Sie ein wenig mit der Grundeinstellung zu kämpfen haben, bei der der Server den Standort des Spielers berechnet. Teilen Sie dies also in Schritte auf, lassen Sie es zuerst funktionieren und arbeiten Sie dann an dem Vorhersagecode, der gerade ausgeführt wird.

Cameron Fredman
quelle
Vielen Dank dafür, dass dieses Delta (in diesem Fall 1 Meile pro Minute) sowohl auf dem Client als auch auf dem Server bekannt ist.
Dolyth
Nun, ich würde das die "Geschwindigkeit" nennen, nicht das Delta. Delta bezieht sich auf die verstrichene Zeit zwischen Frames.
Cameron Fredman
Cool. Ich muss zugeben, dass ich immer noch verwirrt bin, wie dies mit dem Drücken und Halten der Taste mit der Geschwindigkeit zusammenhängt, mit der Nachrichten an den Server gesendet werden.
Dolyth
Leider erschwert so etwas das Zurückspulen / Wiedergeben, wenn Korrekturen vorgenommen werden müssen (Zeitschritte sind unterschiedlich, daher ist es schwierig, den zu verwendenden Frame zu extrapolieren). Ich sende eine ID und wie lange der letzte Frame auf dem Server gedauert hat. Der Server setzt eine "totaltime" -Variable, die dieser entspricht, und aktualisiert sie in Teilen dieser Zeit. Nachdem die Gesamtzeit abgelaufen ist, sendet es die Position, an der sich der Spieler befinden sollte.
untitled
1
Ich denke, Sie beziehen sich auf den Server, der die Zeit zwischen den Paketen verfolgt? Aber was ist, wenn einige Pakete ein paar Sekunden oder Millisekunden haben, nur weil jemand die Steuerung abhebt? Ich wünschte, es gäbe mehr Diagramme zu diesem Thema, die tatsächliche Tastendrücke und Beispiele für Datenpakete säen.
Dolyth