Synchronisieren von Clients mit einem Server und untereinander

9

Was ist der beste Weg, um alle Clients mit einem Server und untereinander zu synchronisieren?

Derzeit verfolgen wir zwei Ansätze:

  1. Wenn ein Client etwas an den Server sendet, sendet der Server sofort Nachrichten an alle Clients, die sofort reagieren.
  2. Einführung einer gewissen Zeitverzögerung, bei der der Server mit der Anweisung "Nachrichten an alle Clients sendet" t.

Der zweite Ansatz scheint eher dazu zu führen, dass alle Clients besser synchronisiert werden (da er eine gewisse Verzögerung aufweist). Ich frage mich jedoch, ob die Reaktionsfähigkeit zu stark verloren gehen würde (dh der Benutzer klickt auf "Springen" und es gibt eine merkliche Lücke zwischen dem Drücken der Taste und dem tatsächlichen Springen).

Es besteht auch die Möglichkeit, dass Clients ihre eigene Position berechnen (und nicht darauf warten, dass Server sagen, dass Sie gesprungen sind). Aufgrund der unvermeidlichen Verzögerung würden die Clients jedoch nicht mehr synchron sein.

Dann gibt es die ganze Frage zwischen TCP und UDP. weil wir es schnell wollen, aber ich würde es auch hassen, wenn der Server sagt, dass Sie sich an einem völlig anderen Ort befinden, als Sie dachten.

Bei all diesen konkurrierenden Anforderungen wird es sehr ungewiss, wie wir dieses Problem angehen sollen. Welcher dieser (oder anderer) Ansätze eignet sich am besten, um Clients und Server synchron zu halten? Welche werden in der Branche tatsächlich eingesetzt?

Smashery
quelle

Antworten:

7

Die schnelle Antwort lautet: Es gibt keinen besten Ansatz.

Alle Spiele enthalten unterschiedliche Architekturen. Jedes Spiel wählt verschiedene Datensätze aus, die gesendet werden sollen, um sich mit anderen Maschinen zu synchronisieren. Dies wirkt sich auf die Entscheidungen aus, die Sie treffen können, wenn Sie entscheiden, wie mit Verzögerungen umgegangen werden soll.

Was Sie in Option 2 angeben - dass Clients Nachrichten senden, auf die zu einem späteren Zeitpunkt reagiert werden soll - ist definitiv ein Ansatz. Tatsächlich verwendet die Source-Engine eine Variante dieses Ansatzes , bei der das Rendern immer 100 ms hinter den lokalen Clientaktionen liegt. Alle Maschinen versuchen, gleichzeitig mit denselben Aktionen zu arbeiten. Dies fügt dem Spiel eine künstliche, nicht wahrnehmbare Verzögerung hinzu, um die tatsächliche Netzwerklatenz zu verbergen.

Wenn Sie diesen Ansatz nicht wählen können, können Sie auch Option 1 auswählen, indem Sie einfach die aktuellsten Daten senden und nach Erhalt Interpolation und Extrapolation (clientseitige Vorhersage) verwenden, um die Latenz zu verbergen. Ich habe diesen Ansatz in mindestens einem Versandspiel verwendet - aber auch hier hängt alles von Ihrem Spiel ab. Möglicherweise können Sie andere Ansätze wählen.

Wenn Sie zwischen TCP und UDP wählen, möchten Sie wahrscheinlich UDP. Es gibt Szenarien , in denen TCP ist ein gangbarer Weg für Ihr Spiel Vernetzung, aber wenn Sie ein Action - Spiel machen, wollen Sie die neuesten Daten so schnell wie möglich. Wenn Sie selbst mit verworfenen Paketen umgehen können, ist UDP die bessere Wahl. (Es gibt Bibliotheken wie ENet , die einen Wrapper um UDP bereitstellen, um Funktionen von TCP zu ersetzen, z. B. zuverlässige Pakete.)

Blair Holloway
quelle
Sie möchten UDP wirklich nicht verwenden. Der Overhead einer korrekt konfigurierten TCP-Verbindung ist minimal und die Hölle, in der die Lieferung nicht in Ordnung ist, sollte niemand durchleben müssen.
Coderanger
2
Es ist keine Frage des Overheads, obwohl TCP einige hinzufügt - die Art und Weise, wie TCP mit verworfenen Paketen umgeht, ist in Spielen, in denen eine große Latenz zwischen Aktion und Reaktion einen großen Unterschied in der Spielbarkeit bewirken kann, grundsätzlich nicht gut . In einem Spiel wie WoW, in dem Aktionen relativ selten sind, funktioniert TCP, aber in einem Spiel wie CounterStrike würde es flach fallen, da ein einzelnes verworfenes Paket Ihre Verbindung drosselt und Sie möglicherweise für eine Sekunde oder länger "zurückbleiben" lässt.
Blair Holloway
Wenn Sie UDP verwenden möchten, ist es am besten, es nicht selbst zu schreiben. Verwenden Sie einen Wrapper wie ENet, der die harte Arbeit für Sie erledigt. Aber meine ursprüngliche Antwort bleibt bestehen: UDP ist der beste Weg, wenn Sie ein Spiel mit einer schnellen Aktion machen.
Blair Holloway
Für mich hat RakNet das Ausführen einer UDP-Verbindung für meine Spiel-Engine extrem einfach gemacht. Es gibt viele Möglichkeiten, wie Sie Ihr Paket senden möchten, z. wie man sie bestellt, sollte das Paket erneut gesendet werden, wenn es
verworfen wird
3

Hier sind ein paar gute Links, die eine Menge Networking für Spiele abdecken.

Und dies ist der erste Teil der mehr praktischen Netzwerkserie. http://gafferongames.com/networking-for-game-programmers/udp-vs-tcp/

Für die Geschichte. 'Es tut uns leid, aber als Spam-Präventionsmechanismus können neue Benutzer nur maximal einen Hyperlink posten. Verdiene dir 10 Ruf, um mehr Hyperlinks zu posten. ' Schauen Sie sich trotzdem auf seiner Website um.

jsimmons
quelle
1

Da Sie Clients und Server erwähnen, gehe ich davon aus, dass es sich um eine Client / Server-Architektur handelt, bei der der Server die Autorität für den Status aller Objekte ist.

Hinweis: Die Alternative ist eine Peer-to-Peer-Architektur, bei der der Eigentümer eines Objekts die Berechtigung für dieses Objekt ist.

Es gibt bereits eine bewährte Methode zum Synchronisieren von sich bewegenden Objekten mithilfe der Client-Server-Architektur. Es heißt Dead Reckoning. .

Ein guter Weg, dies in einem Spiel zu implementieren, wäre folgender:

  1. Clients senden Eingaben an den Server.
  2. Der Server aktualisiert die Spielobjekte (Beschleunigungen und Richtungen) und sendet sie an die Clients zurück.
  3. Clients verwenden diese aktualisierten Werte, um die Bewegung der Objekte lokal zu simulieren.
  4. Gelegentlich sendet der Server eine Positionskorrektur, um eine Drift zu vermeiden.
  5. Spülen; wiederholen.
JanSolo
quelle