Wie kann man bewegte Objekte mit clientseitiger Vorhersage kompensieren?

11

Ich implementiere einen Spieleserver, der Star Control-ähnlichen Nahkampf unterstützt . Sie haben also Schiffe, die fliegen und schießen, mit supereinfacher Geschwindigkeits- / Beschleunigungs- / Dämpfungsphysik, um Bewegungen anzutreiben.

Geben Sie hier die Bildbeschreibung ein

Ich habe Valve, Gafferon und Gambetta gelesen und den Gambetta-Algorithmus für die Kundenvorhersage implementiert :

Geben Sie hier die Bildbeschreibung ein

Die Client-Vorhersage funktioniert auf dem Player-Schiff, indem die Position des Servers sofort aktualisiert und die vom Server noch nicht verarbeitete Eingabe erneut auf das Player-Schiff angewendet wird.

Leider funktioniert es für mein Spiel nicht gut. Ich glaube, das hat damit zu tun, dass Gambettas Beispiel keine Objekte berücksichtigt, die sich bereits bewegen, oder Befehle, die Schritt für Schritt aktualisiert werden. (mit "Schritt" meine ich Rahmen). In meinem Spiel drückt der Spieler nach oben, um das (sich bereits bewegende) Schiff zu beschleunigen, das sich auf dem Client weiter bewegt, den Befehl an den Server sendet und normalerweise im nächsten Schritt den Weltschnappschuss vom Server empfängt. Ich bekomme eher etwas wie:

Geben Sie hier die Bildbeschreibung ein

Der Player-Befehl wird in Client- Schritt 3 ausgeführt , auf dem Server jedoch nur in Server- Schritt 5 . Wenn der Client im Schritt 6 des Clients den Weltschnappschuss empfängt , ist die Vorhersage weit entfernt, insbesondere bei schnelleren Geschwindigkeiten.

Der Kern des Problems besteht darin, dass der Client den Befehl in Schritt 5 ausführt , der Server ihn jedoch in Schritt 6 ausführt . Ich dachte darüber nach, den Client-Schritt möglicherweise mit dem Befehl zu senden und den Server zurücksetzen zu lassen und den Befehl mit dem Client-Zeitschritt erneut auszuführen. Dies kann jedoch zu einer Reihe anderer Probleme führen - z. B. was mit Befehlen passiert, die seit dem Rollback empfangen wurden, oder wie betrügerische Clients durch Ändern des gesendeten Schritts ausgenutzt werden können.

Beim Lesen und Ansehen von Videos wie diesem von Google wird ein anderer Ansatz erwähnt, bei dem Sie die Position des Spielers schrittweise ändern, um sie in wenigen Schritten an die des Schnappschusses anzupassen.

Meine Fragen:

  • Können Sie Gambettas Algorithmus mit konstanter Schrittbewegung arbeiten lassen? Oder ist es konzeptionell nicht mit meinem Spiel kompatibel?

  • Ist eine schrittweise Interpolation über Schritte dann der richtige Weg? Wenn ja, wie interpolieren Sie ein sich bereits bewegendes Objekt von der Client-Position, um es an das anzupassen, was gerade vom Server empfangen wurde?

  • Können diese Methoden, die schrittweise Interpolation und der Gambetta-Algorithmus zusammenarbeiten, oder schließen sie sich gegenseitig aus?

OpherV
quelle
Ich habe das Gleiche getan und bin auf genau das gleiche Problem gestoßen. Sobald ich Geschwindigkeiten hinzugefügt habe, die den Serverstatus anwenden und Eingaben erneut anwenden, wurden die bereits behandelten Geschwindigkeitsänderungen beseitigt. Ich habe versucht, alle Updates seit der letzten empfangenen Nachricht erneut anzuwenden, aber es ist noch nicht sehr reibungslos. Haben Sie jemals eine Lösung dafür gefunden?
MakuraYami
@MakuraYami Ja - Ich habe angefangen, einen Artikel zu schreiben, der die Lösung beschreibt. Wird bald aktualisiert!
OpherV
Ich habe mehr an meinem Projekt gearbeitet und eine brauchbare Lösung und einige weitere gute Ressourcen gefunden, die über dieses Problem sprechen. Ich bin interessiert, weiter zu diskutieren, Lösungen zu vergleichen usw. Lassen Sie mich wissen, wo ich Sie kontaktieren kann :)
MakuraYami
@ Makurayami mein Benutzername bei Google Mail
OpherV

Antworten:

5

In den 6 Monaten, seit ich diese Frage gestellt habe, habe ich einen vollständigen Open-Source-Spieleserver entwickelt, um genau dieses Problem (und viele andere!) Zu lösen : http://lance.gg

Geben Sie hier die Bildbeschreibung ein

Die F & E ermöglicht es mir nun, meine eigenen Fragen zu beantworten:

  • Können Sie Gambettas Algorithmus mit konstanter Schrittbewegung arbeiten lassen? Oder ist es konzeptionell nicht mit meinem Spiel kompatibel?

    Der Gambetta-Algorithmus funktioniert nicht, wenn die Bewegung der Entität nicht deterministisch ist (aus der POV des Kunden). Wenn eine Entität ohne Eingabe durch die Physik oder andere Akteure betroffen sein kann, muss beispielsweise ein aufwendigerer Ansatz gewählt werden.

  • Ist eine schrittweise Interpolation über Schritte dann der richtige Weg? Wenn ja, wie interpolieren Sie ein sich bereits bewegendes Objekt von der Client-Position, um es an das anzupassen, was gerade vom Server empfangen wurde?

    Dies berührt ein anderes Thema, nämlich die Clientabstimmung von Serveraktualisierungen. Die schrittweise Interpolation funktioniert, aber für sehr schnelle Spiele wie das fragliche ist es besser, die Extrapolation tatsächlich zu implementieren

  • Können diese Methoden, die schrittweise Interpolation und der Gambetta-Algorithmus zusammenarbeiten, oder schließen sie sich gegenseitig aus?

    Sie können zusammenarbeiten, jedoch nur, wenn die Entitätsbewegung vom Client-POV deterministisch ist. Es wird also nicht funktionieren, wenn die Entität von Physik oder Pseudophysik wie Einfügen, Ziehen usw. betroffen ist. '

OpherV
quelle
1

Ihr Spiel scheint zu "Echtzeit" zu sein, um in Zeitschritten zu denken. Ich würde nur in "Runden" denken, wenn das Spiel als "rundenbasiert" betrachtet werden kann. Andernfalls geben Sie einfach die Idee von Kurven oder Schritten auf. Dann wird alles einfacher :)

Beachten Sie, dass Sie für Ihren Player lokal Vorhersagen treffen und nur für andere Entitäten interpolieren (wie im 3. Artikel der Serie erläutert). Der Umgang mit Serveraktualisierungen für Objekte, die bereits verschoben wurden, ist die serverseitige Abstimmung, die in der unteren Hälfte des zweiten Artikels (dem, auf den Sie verlinkt haben) erläutert wird.

Hoffe das hilft :)

ggambett
quelle
Nur zur Verdeutlichung - mit "Schritt" meine ich "Frame", der 60 Mal pro Sekunde ausgeführt wird. Ich nenne es Schritt (und nicht Frame), um den tatsächlichen Spielverlauf vom Rendering zu unterscheiden, und im Idealfall werden beide mit 60 pro Sekunde synchronisiert. Ich habe bereits Ihre Version der serverseitigen Abstimmung implementiert, die hervorragend funktioniert. Diese Frage bezieht sich nur auf das Spielerschiff, das sich unabhängig vom Spielerbefehl ständig bewegt (aufgrund von Trägheit). Hier liegt meine Schwierigkeit. Irgendwelche Gedanken dazu? :)
OpherV
Frames unterscheiden sich von Schritten. Die Schritte bewegen sich in einer konstanten, vorhersehbaren Reihenfolge. Frames verschieben eine variable Zeitspanne, daher muss jeder Fortschritt mit der Deltazeit für diesen Frame multipliziert werden.
Tealr
@Tealr in der Tat, weshalb ich zunächst den Begriff "Schritt" verwendet habe - ich wollte nur klarer machen, dass die Verwendung von "Schritt" nicht auf rundenbasierte Spiele beschränkt ist, und in meinem Spiel dauert ein Schritt genau 1 / 60 Sekunden unabhängig vom Rendern.
OpherV
Nur etwas, das ich für mein eigenes Experimentieren notiere: 1 / 60s. ist ungewöhnlich schnell und ich wette, dass die meisten Online-Spiele mit mehr als 1x1 Teilnahme bei 1/10 funktionieren. Updates oder so ungefähr.
Patrick Hughes