Ich implementiere einen Multiplayer-Asteroiden-Klon, um mehr über die Client / Server-Netzwerkarchitektur in Spielen zu erfahren. Ich habe Zeit damit verbracht, die Veröffentlichungen von GafferOnGames und Valve über deren Client / Server-Technologie zu lesen. Ich habe Probleme mit zwei Konzepten.
Derzeit besitze ich einen autoritativen Spieleserver, der mit box2d die Physik simuliert und etwa 20 Mal pro Sekunde den Status der Welt an Kunden sendet. Jeder Client verfolgt die letzten erhaltenen Snapshots und wechselt zwischen zwei Status, um die Bewegung von Sprites auszugleichen. Es ist jedoch nicht so glatt. Es kann für eine Weile glatt sein, dann ruckelt es ein bisschen, dann wieder glatt usw. Ich habe sowohl TCP als auch UDP ausprobiert, beide sind ungefähr gleich. Irgendeine Idee, was mein Problem sein könnte? (Hinweis: Ich habe dies zuerst für Einzelspieler implementiert und die Sprite-Bewegung ist mit 60 fps perfekt flüssig, wenn die Physik-Welt nur 20 Mal pro Sekunde aktualisiert wird.)
Um das erste Problem zu lösen, dachte ich, der Client sollte vielleicht auch eine Box2D-Simulation ausführen und einfach die Positionen seiner Sprites aktualisieren, damit sie mit den Server-Snapshots übereinstimmen, wenn sie nicht übereinstimmen. Ich dachte, dies könnte reibungsloser sein, da meine Single-Player-Implementierung reibungslos verläuft. Ist das eine gute Idee?
Auch wenn das oben genannte Problem nicht behoben werden kann, ist es für die clientseitige Vorhersage erforderlich? Wenn ein Spieler beispielsweise versucht, sein Schiff zu bewegen, wie kann er dann feststellen, ob er einen Asteroiden, eine Mauer oder ein feindliches Schiff ohne physikalische Simulation getroffen hat? Es scheint, als würde ihr Schiff das Objekt passieren, mit dem es kollidieren soll, bevor sie einen Schnappschuss vom Server erhalten, der besagt, dass sie das Objekt getroffen haben.
Vielen Dank!
quelle
+-*/
" ist völlig falsch. Alle diese Operationen in IEEE-754 können je nach Implementierung variieren. Sehen Sie hier und hier für weitere Informationen.Es sieht wahrscheinlich nicht so gut aus, da die Interpolation zwischen ihnen davon abhängt, dass immer der nächste Datensatz zur Interpolation zur Verfügung steht. Dies bedeutet, dass bei einer kurzen Verzögerung alles warten muss, um aufzuholen.
Es gibt einen alten Artikel in GameDev über die Verwendung von kubischen Splines, um die Position eines Objekts nach dem Punkt vorherzusagen, an dem Sie zuletzt Daten dafür hatten. Was Sie dann tun, ist, diese Position zu verwenden und dann den Spline anzupassen, wenn Sie neue Daten erhalten, um die neue Position zu berücksichtigen. Es ist wahrscheinlich auch viel billiger als das Ausführen einer zweiten Physiksimulation, und Sie müssen sich nicht entscheiden, wem Sie vertrauen, da Sie den Client, der es erstellt, explizit implementiert haben. :)
quelle
Ich habe selbst ähnliche Sachen gemacht und Box2D nur auf den Clients ausgeführt. Ich habe es so gemacht, dass der Client seine eigene Simulation so gut wie von selbst ausführt und die aktuelle Geschwindigkeit (und Rotation) für jedes Synchronisierungspaket an den Server sendet. Der Server sendet diese Informationen dann an andere Spieler, die die neu empfangenen Geschwindigkeiten auf die replizierten Entitäten setzen. Es war sehr reibungslos, ohne merkliche Unterschiede zwischen den Kunden.
Das Problem hierbei ist natürlich, dass es keine zentrale Kontrolle über Entitäten gibt, aber ich denke, dass dies auch auf der Serverseite durch eine serverseitige Simulation der Physik möglich ist
quelle
Ich persönlich würde es vorziehen, die Simulationen nur auf dem Server auszuführen und Änderungen an linearen / Winkelgeschwindigkeiten / Beschleunigungen der beteiligten Objekte zu übertragen, wann immer sie auftreten. Wenn ein bestimmtes Objekt aus irgendeinem Grund seine physikalischen Eigenschaften ändert (z. B. die oben genannten Geschwindigkeiten und Beschleunigungen), wird diese spezielle Änderung vom Server an den Client gesendet und der Client ändert seine Seite von Objektdaten entsprechend.
Der Vorteil gegenüber Ihrer aktuellen Implementierung besteht darin, dass die Notwendigkeit clientseitiger Interpolationen entfällt und ein sehr genaues Verhalten für die Objekte erzeugt wird. Das Problem ist, dass diese Methode sehr anfällig für Latenzen ist, die zu einem sehr großen Problem werden, wenn die Spieler geografisch zu weit voneinander entfernt sind.
Was Frage 1 betrifft, so würde das Problem in Latenzschwankungen bestehen, da es keine absolute Garantie dafür gibt, dass zwischen jedem Empfang des Schnappschusses ein genau perfektes Intervall von 20 Sekunden liegt. Lassen Sie mich veranschaulichen (wobei "t" die in Millisekunden gemessene Zeit ist):
1) Bei t = 20 seit dem Start des Spiels hat der Client einen Schnappschuss erhalten und die Interpolation erfolgreich und reibungslos durchgeführt.
2) Bei t = 40 gab es eine Latenzzeit zwischen dem Server und dem Client, und der Schnappschuss traf nur tatsächlich bei t = 41 ein.
3) Bei t = 60 hat der Server einen weiteren Snapshot gesendet, aber eine Sekunde der Simulation wurde wegen der Latenzzeit clientseitig verschwendet. Wenn der Schnappschuss bei t = 60 ankommt, interpoliert der Client nicht die 40 und 60 Zeitpunkte, sondern die Zeitpunkte 41 bis 60, wodurch ein anderes Verhalten erzeugt wird. Diese Ungenauigkeit könnte die Ursache für das eventuelle "Ruckeln" sein.
Was Frage 2 betrifft, könnte Ihre Idee funktionieren, wenn Sie etwas implementieren, das effizient nachverfolgt, ob jedes Objekt wirklich Client-Server-synchronisiert ist, ohne dass Pakete für jeden Frame gesendet werden müssen, um die Position der Objekte mitzuteilen. Selbst wenn Sie dies in diskreten Intervallen tun, werden Sie nicht nur auf dasselbe Problem wie bei Frage 1 stoßen, sondern auch über zu große Datenmengen verfügen, um diese zu übertragen (was eine schlechte Sache ist).
quelle