Ich arbeite an einer 2D-Server-Client-Multiplayer-Game-Engine (die Sie hier ausprobieren können ). Es verwendet WebRTCs DataChannel
. (Die Verbindungen sind Peer-to-Peer-Verbindungen, der Host-Peer fungiert jedoch weiterhin als Server.)
Das größte Problem (abgesehen von der Konnektivität) ist die lokale Eingabevorhersage. Wir machen das Übliche: Beim Drücken einer Taste bewegen sich die Spieler sofort, teilen dem Host mit, welche Tasten gedrückt werden, empfangen Daten vom Host und vergleichen sie mit der historischen Position. Die Position wird im Laufe der Zeit korrigiert, wenn ein Unterschied besteht. Dies funktioniert gut mit geringem Paketverlust oder PDV , auch wenn der Ping hoch ist.
Bei Verlust oder PDV kann die Abweichung größer sein. Ich denke, das liegt daran, dass der Host es später herausfindet, wenn das erste Paket, das eine Änderung der Eingabe anzeigt, verzögert oder verworfen wird, und beginnt, diesen Player später zu ändern, als es die lokale Eingabevorschrift anzeigt.
Wenn sich der Spieler bewegt, erhöhen wir den Umfang der angewendeten Korrektur, da dies weniger auffällt. Dies scheint Lücken zu schließen, wenn Sie anfangen, sich zu bewegen, und während Sie sich bewegen. Jede Korrektur ist jedoch deutlicher, wenn sie abrupt zum Stillstand kommt. Dann, wenn der PDV oder Verlust bedeutet, dass der Host denkt, dass er später aufgehört hat, überschießt der Host das Signal, sendet Daten zurück und sagt, dass sie etwas weiter vorne liegen, und die Korrektur lässt den Spieler ein wenig driften. Bei schuppigen Verbindungen driften die Spieler oft merklich, nachdem sie zum Stillstand gekommen sind.
Ich habe das in anderen Spielen nicht bemerkt. Wie kann dies gemildert werden?
quelle
Antworten:
Die Netzwerkschicht muss einen vereinbarten Takt haben. Sie können sich zu Beginn des Spiels auf einen Zeitwert einigen (und ihn bei Abweichungen regelmäßig neu synchronisieren), damit der Host weiß, wie lange es gedauert hat, bis ein bestimmtes Paket tatsächlich eingetroffen ist und wann der Client die Aktion ausgeführt hat, und umgekehrt.
In diesem Artikel erfahren Sie, wie Sie Uhren in Spielen synchronisieren können. Da sind andere. Die spezifischen Mittel spielen keine Rolle.
Die zweite Hälfte des Problems besteht darin, dass der Server die Eingabe nach dem Zeitpunkt anwendet, an dem der Client die Eingabe nicht mehr anwendet. Dies erfordert einen Puffer mit früheren Bewegungen auf dem Server und eine gewisse Logik auf dem Client, um Bewegungseingaben vom Server nach der letzten bekannten Bewegung zu ignorieren.
Zunächst der Serverpuffer. Der Server muss den Zeitstempel der letzten vom Player empfangenen Eingaben verfolgen. Es braucht auch alle Bewegungen, die es einem Spieler auferlegt, den Zeitstempel des Uhrwerks. Wenn eine Eingabe empfangen wird, werden alle letzten Bewegungen, für die ein neuer Zeitstempel als das Eingabepaket angewendet wurde, verworfen, und alle Bewegungen werden aus dem Eingabepaket erneut angewendet. Wenn der Server den Spieler aufgrund einer Eingabe übersteuert, werden diese Bewegungen durch die aktualisierte Eingabe gelöscht, und die neue Position des Spielers basiert auf dem neuesten Eingabewissen des Servers.
Auf der Clientseite weiß der Client, wann er zuletzt Eingaben an den Server gesendet hat. Da jedes Player-Update vom Server mit der Uhrzeit der letzten dem Server bekannten Eingabe versehen sein sollte, kann der Client Server-Updates mit abgelaufener Eingabe ignorieren und sich nur an die Client-Vorhersage halten. Eventuell werden neue Server-Updates mit aktuellen Eingaben eintreffen und der Client kann diese korrigieren.
Der Server muss die Eingabetakte validieren und sicherstellen, dass sie nicht zu sehr von den Erwartungen abweichen, um Betrug zu verhindern. Der Eingangstakt sollte nicht drastisch größer sein als die zu berechnende halbe Umlaufzeit. Klemmen Sie alle, die sich in einem angemessenen Bereich befinden (
[Now-2*RTT,Now]
z. B.).Kunden werden eine Menge Jitter bei den Avataren anderer Spieler bemerken, wenn die Latenzzeit hoch ist, da sie aufgrund veralteter Eingaben Aktualisierungen vom Server erhalten, aber nicht wissen können, ob diese veraltet sind, und der Server dann möglicherweise basierend auf den Einstellungen andere Standorte sendet die aktualisierte Eingabe, die er erhalten hat (und das Löschen eines Teils seines Verlaufs und die erneute Wiedergabe mit der neuen Eingabe). Dieses letzte Problem, bei dem andere Spieler Ihren Avatar-Jitter sehen, ist nicht wirklich zu beheben. Latenzprobleme und Spieler, die auf Verbindungen mit hoher Latenz angewiesen sind, werden bei anderen Spielern eine Menge Unruhe erleben, selbst wenn sich ihr eigener Spieler reibungslos bewegt. Die einzige Korrektur besteht darin, auf besseren Verbindungen oder mit Peers / Servern mit geringerer Latenz zu spielen.
quelle
Ich habe zuverlässige UDP-Nachrichten verwendet, um Änderungen des Tastenzustands und unzuverlässige UDP-Nachrichten für die Positionskorrektur anzuzeigen. Grundsätzlich haben mir die folgenden Artikel sehr geholfen: https://developer.valvesoftware.com/wiki/Source_Multiplayer_Networking
Hier wird die Bewegungsvorhersage beschrieben, indem Spielerzustände in konstanten Zeitintervallen entsprechend der Ankunft der Positionskorrekturnachrichten für etwa 20 oder 30 Zustandsspeicherungen gespeichert werden. Es sieht also so aus, als würden Ihre Remote-Spieler in einer nicht allzu weit zurückliegenden Vergangenheit leben, wenn Sie ständig die Vorhersage-Technik anwenden :) Aufgrund der Netto-Nachrichtenlatenz können Sie Ihre Objektposition ungefähr in der Zeit ermitteln, in der die Nachricht gerade vom Host gesendet wurde.
Die aktuelle Position auf dem Bildschirm kann dann mithilfe von Lerp-Mathematik (lineare Interpolation) reibungslos in die vorhergesagte Position übersetzt werden. Die Idee ist, Werte in den Zeitabständen zwischen den Korrekturpaketen zu interpolieren. Es sieht also so aus, als würde sich das angezeigte Objekt immer in Richtung einer vorhergesagten Position bewegen. Für den Interpolationswert nehme ich die 1 geteilt durch "mittlere Nachrichtenlatenz" geteilt durch "mittlere Bildwiedergabezeit", so dass die Bewegung glatt aussieht.
In diesem Szenario berechnet das Spiel auf allen Clients und der Server korrigiert von Zeit zu Zeit die Werte wie Geschwindigkeit und Position.
Eine weitere Sache, die in diesem Fall sehr hilfreich ist: Optimieren Sie Ihre Spielelogik, damit Sie die Latenzzeiteffekte leicht negieren können, indem Sie sicherstellen, dass Server und Clients basierend auf den Eingaben der Spieler ein nahezu ähnliches Verhalten emulieren können.
Ich habe das gesamte Schema, das ich in meinem Projekt verwendet habe, beschrieben, also hoffe ich, dass Sie die Antwort auf Ihre Frage finden.
quelle