Was soll ich in einem Echtzeit-FPS-Spiel an den Server senden?
23
Was ist der richtige Weg, um die Position unseres lokalen Spielers dem Server mitzuteilen? Einige Dokumente sagen, dass es besser ist, die Eingaben zu senden, wenn sie produziert werden. In einigen Dokumenten wird angegeben, dass der Client seine Position in einem festen Intervall sendet.
Beim Senden der Eingaben: Was soll ich tun, wenn der Spieler die Richtungstasten gedrückt hält? Das bedeutet, dass ich in jedem Frame ein Paket an den Server senden muss. Ist es nicht zu viel? Und es gibt auch die Drehung des Players über die Mauseingabe. Hier ist ein Beispiel:
Was ist mit dem Senden der Position in einem festen Intervall. Es werden zu wenige Nachrichten an den Server gesendet. Es verringert aber auch die Reaktionsfähigkeit.
Einfache Antwort: Betrügen Sie oder seien Sie nicht so genau!
Wenn Sie einen Shooter online gespielt haben, haben Sie höchstwahrscheinlich das sogenannte "Rubber Banding" erlebt, wenn Ihre Verbindung zum Server schlecht ist.
Dies wird dadurch verursacht, dass Ihr Kunde Ihre Position von Zeit zu Zeit korrigiert.
Grundsätzlich, was passiert auf beiden Seiten:
Der Server verfolgt Ihre Bewegung und sendet erwartungsgemäß Aktualisierungen an die Clients. Dies müssen nicht immer vollständige Updates sein. Alle x Frames können vollständig aktualisiert werden, alle anderen Frames senden Sie nur neue Geschwindigkeitsvektoren (falls Änderungen vorliegen).
Ihr eigener Client erlaubt Ihnen, sich frei zu bewegen, verwendet jedoch die vom Server bereitgestellten Aktualisierungen, um Ihre Position zu korrigieren / anzupassen. Dadurch wird sichergestellt, dass das Spiel reagiert, auch wenn Sie die Position nicht Frame für Frame aktualisieren.
Aber wie wird mit Eingaben umgegangen? Ihr Kunde sendet Ihre Position an den Server "Ich bin dorthin umgezogen.". Der Server überprüft dieses Update (z. B. sollten Sie in der Lage sein, sich so schnell dorthin zu bewegen?) Und ob es gültig ist, Sie zu bewegen (oder Ihr Update abzulehnen, was zu "Gummibändern" führt).
Also ja, Ihr Ansatz mit festen Intervallen wird höchstwahrscheinlich funktionieren und ausreichen.
Aber auch wenn Sie Eingaben senden und Bewegungen auf beiden Seiten verarbeiten möchten, müssen Sie nicht "Button ist noch gedrückt" senden. Senden Sie stattdessen ein Ereignis, wenn die Taste gedrückt wird, und ein anderes, wenn die Taste losgelassen wird.
Ja, ich kann das Drücken und Loslassen der Taste verfolgen. Aber was ist mit Mauseingaben? Es ändert sich ständig.
Syloc
6
"Senden Sie stattdessen ein Ereignis, wenn die Taste gedrückt wird, und ein anderes, wenn die Taste losgelassen wird." - Richtig, aber es müssen Überprüfungen durchgeführt werden, um sicherzustellen, dass das Ereignis "bei Veröffentlichung" abhängig von den Spielregeln erzwungen wird. Im Mehrspielermodus von Rainbow Six Vegas 2 kann ein Spieler beispielsweise mit dem Abfeuern seiner Waffe beginnen, und ein (leider häufig auftretender) Fehler führt dazu, dass die Meldung "Abfeuern beenden" den Server nicht erfolgreich erreicht. Dies führt dazu, dass der Schuss-Ton für den Rest des Spiels in einer Endlosschleife verbleibt. Nur ein Beispiel, vor dem man auf der Hut sein sollte. youtu.be/GOQIbLCy7m8?t=9m10s
Mike Baxter
@syloc: Behandle es einfach clientseitig und lasse den Server bestimmen, ob die Bewegung gültig / möglich ist (um Dinge wie Teleport-Hacks und ähnliches zu verhindern).
Mario
@syloc Legen Sie einfach ein Intervall für die Maus fest. Um jedoch zusätzliche Bandbreite zu sparen, überprüfen Sie auf der Clientseite, ob diese geändert wurde. Wenn es einen Zeitraum ohne Mausbewegung gibt, müssen Sie keine weiteren Nachrichten darüber senden.
8.
Bei einem meiner Jobs hatte ich einen Ingenieur, der sich praktisch selbst in den Wahnsinn getrieben hat, um das Federverhalten für verpasste Positionsaktualisierungen für die Einwahl zu optimieren (vor 13 Jahren). Jetzt sehe ich Spiele mit viel Bandbreite und lächerlich geringer Latenz, die unter diesem Problem leiden, anscheinend wird das Problem nie mehr weg sein oder die Leute kümmern sich heutzutage viel weniger darum.
Diese erläutern, warum das Senden von Paketen mit festem Intervall empfohlen wird. Um es kurz zu machen, es ist in der Tat hauptsächlich wichtig für Pakete, die vom Server gesendet werden.
Das Senden eines Pakets ist kostenpflichtig und die maximale Größe eines Netzwerkpakets beträgt ca. 1,5 KB. Wenn Sie also beispielsweise 16 Spieler auf Ihrem Server haben, könnte jeder Frame, wenn Sie die Bewegung für einen Spieler berechnen, mit einem naiven Code nach jeder Bewegungsauflösung ein Aktualisierungspaket an jeden Spieler senden, also 16 * 16 = 256 Pakete. Wenn Sie eine Bildrate von 30 haben, sind das 7680 Pakete.
Ein besserer Ansatz besteht darin, an jedem Frame-Anfang einen Puffer zu erstellen, darin Ihre 16 berechneten Positionsaktualisierungen zu verketten und diese dann an Ihre 16 Spieler zu senden.
Sie senden jetzt nur 480 Pakete pro Sekunde für die gleichen Ergebnisse.
Im Player-zu-Server-Fall bedeutet dies nur, dass Sie im selben Paket ein Maximum an Daten senden sollten, wie z. schaute Position, Aktionen genannt diesen Rahmen und so weiter.
Zum zweiten Teil Ihrer Frage - die Art und Weise, wie ich das Verzögerungsgefühl reduziere, bestand darin, diese Informationen in jedem Frame an den Server zu senden:
Aktuelle Position des Players (wird vom Server verwendet, um zu überprüfen, ob die Positionen auf Server- und Player-Seite nicht zu stark desynchronisiert sind).
Geschätzte Spielerposition in 1 Sekunde: Vom Kunden berechnet: Wenn der Spieler die Mausrichtung nicht ändert und die Tastatur für 1 Sekunde in ihrem aktuellen Zustand belässt, wo wird der Spieler sein? (Wir kümmern uns nicht um Kollisionen.) Wenn sich der Spieler nicht bewegt, ist seine geschätzte Position in 1 Sekunde seine aktuelle Position.
Die Position, auf die er schaut.
Jedes Mal, wenn der Server diese Informationen empfängt, aktualisiert er die zukünftige Position und die betrachtete Position und die Spielerentität bewegt sich schließlich in Richtung ihrer zukünftigen Position.
Spieler werden nie exakt synchronisiert, aber die Eingabe erfolgt sofort (was für mich am wichtigsten ist), und ich habe vorhergesagte Positionen als genau genug für mich befunden.
"Spieler sind nie genau synchronisiert" Ich denke, es ist auch wichtig zu erwähnen, dass die Genauigkeit hier vom tatsächlichen Spiel abhängt. Ein klassisches MMO, in dem Sie einfach auf Objekte klicken und diese auswählen, benötigt für so gut wie alles keine perfekte Genauigkeit. In einem Shooter ist jedoch eine gute bis perfekte Synchronisierung unerlässlich.
Mario
Die Sache ist, dass niemand, der bei klarem Verstand ist, TCP als FPS verwendet. Sie würden sich lieber mit komplizierter Neu-Sequenzierung und fehlenden Datagrammen befassen, als den Overhead von TCP zu verursachen.
Wenn Sie es noch nicht getan haben, empfehle ich Ihnen, diese beiden ausführlichen, aber verständlichen Artikel zu lesen: https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking und http://fabiensanglard.net/quake3/network.php .
Diese erläutern, warum das Senden von Paketen mit festem Intervall empfohlen wird. Um es kurz zu machen, es ist in der Tat hauptsächlich wichtig für Pakete, die vom Server gesendet werden.
Das Senden eines Pakets ist kostenpflichtig und die maximale Größe eines Netzwerkpakets beträgt ca. 1,5 KB. Wenn Sie also beispielsweise 16 Spieler auf Ihrem Server haben, könnte jeder Frame, wenn Sie die Bewegung für einen Spieler berechnen, mit einem naiven Code nach jeder Bewegungsauflösung ein Aktualisierungspaket an jeden Spieler senden, also 16 * 16 = 256 Pakete. Wenn Sie eine Bildrate von 30 haben, sind das 7680 Pakete.
Ein besserer Ansatz besteht darin, an jedem Frame-Anfang einen Puffer zu erstellen, darin Ihre 16 berechneten Positionsaktualisierungen zu verketten und diese dann an Ihre 16 Spieler zu senden.
Sie senden jetzt nur 480 Pakete pro Sekunde für die gleichen Ergebnisse.
Im Player-zu-Server-Fall bedeutet dies nur, dass Sie im selben Paket ein Maximum an Daten senden sollten, wie z. schaute Position, Aktionen genannt diesen Rahmen und so weiter.
Zum zweiten Teil Ihrer Frage - die Art und Weise, wie ich das Verzögerungsgefühl reduziere, bestand darin, diese Informationen in jedem Frame an den Server zu senden:
Aktuelle Position des Players (wird vom Server verwendet, um zu überprüfen, ob die Positionen auf Server- und Player-Seite nicht zu stark desynchronisiert sind).
Geschätzte Spielerposition in 1 Sekunde: Vom Kunden berechnet: Wenn der Spieler die Mausrichtung nicht ändert und die Tastatur für 1 Sekunde in ihrem aktuellen Zustand belässt, wo wird der Spieler sein? (Wir kümmern uns nicht um Kollisionen.) Wenn sich der Spieler nicht bewegt, ist seine geschätzte Position in 1 Sekunde seine aktuelle Position.
Die Position, auf die er schaut.
Jedes Mal, wenn der Server diese Informationen empfängt, aktualisiert er die zukünftige Position und die betrachtete Position und die Spielerentität bewegt sich schließlich in Richtung ihrer zukünftigen Position.
Spieler werden nie exakt synchronisiert, aber die Eingabe erfolgt sofort (was für mich am wichtigsten ist), und ich habe vorhergesagte Positionen als genau genug für mich befunden.
quelle