Ich habe die Grundlagen von TCP-Sockets, UDP-Kommunikation usw., kann aber nicht viel darüber finden, wie diese auf eine Echtzeit-Spielumgebung angewendet werden können.
Ich habe einen Pong-Klon mit 4 Spielern und muss die Paddelpositionen zwischen den drei Clients und dem Server synchronisieren (der Server ist der vierte Spieler). Derzeit verwende ich UDP, um Echtzeit-Updates (Paddelbewegungen) zu senden, und TCP, um die Spielelobby usw. einzurichten.
Ist es eine SCHLECHTE Sache, riesige Mengen an UDP-Verkehr zu spammen? Sollte ich etwas wie DCCP auf seine Überlastungsmerkmale untersuchen? Oder ist das bei einem kleinen Projekt wie diesem nicht wirklich ein Problem?
Wann sollten Synchronisierungsnachrichten zwischen Client / Server gesendet werden? Derzeit spammt der Server UDP-Pakete mit dem aktuellen Spielstatus so schnell wie möglich aus, und Clients spammen ihre Paddelposition so schnell wie möglich an den Server zurück. Ist das der beste Weg, es zu tun? Gibt es eine Verzögerung, die ich hinzufügen sollte, damit Nachrichten alle X Millisekunden gesendet werden, oder sollte ich nur Nachrichten senden, wenn Ereignisse eintreten? (zB Paddelgeschwindigkeit aufgrund von Benutzereingaben geändert)
Wäre es besser, Kunden dazu zu bringen, ihre Paddelpositionen Peer-to-Peer miteinander zu kommunizieren?
Ich stelle diese Fragen im Kontext von Pong, bin aber auch daran interessiert, wie diese Probleme in anderen Spielen oder allgemeinen Lösungen überwunden werden.
quelle
Antworten:
Haben Sie ein konfigurierbares Aktualisierungsintervall (damit Sie 5 Pakete pro Sekunde oder 20 optimieren und ausprobieren können), und jeder Frame prüft, ob es Zeit ist, ein Update zu senden. Sie mögen mit einem einfachen Spiel einverstanden sein, das Pakete für jedes Ereignis sendet, aber in einem komplexeren Spiel ist dies nicht praktikabel. Denken Sie auch daran, dass ein Paket-Overhead anfällt. Wenn Sie also eine Reihe kleiner Pakete senden, verschwenden Sie Bandbreite.
In jedem Aktualisierungsintervall sendet jeder Client seine Paddelposition entweder an den Server oder an jeden Client (Peer-Peer). Lassen Sie den Server auch die Ballposition und einen Geschwindigkeitsvektor senden. Jeder Kunde kann den gleichen Bildschirmzeichnungscode wie im Einzelspieler-Modus ausführen, sodass die Bewegung des Balls reibungslos verläuft. Im Mehrspielermodus senden Sie jedoch nur den Server in regelmäßigen Abständen die Positions- / Geschwindigkeitsaktualisierungen für den Ball (und wenn Sie möchten, jedes Mal, wenn er etwas trifft).
Lassen Sie die Ballpositionsaktualisierungen auf eine Spielzeit aller Clients verweisen, damit Sie Pakete außerhalb der Reihenfolge verwerfen und sogar die Interpolation der Ballposition genauer gestalten können (Sie kennen die Position und Geschwindigkeit zu einem bestimmten Zeitpunkt in der Vergangenheit, damit Sie die neue interpolieren können Position).
Bei diesem Modell mit einem verzögerten Spiel kann es vorkommen, dass sich der Ball manchmal rückwärts bewegt oder ein wenig herumspringt. Aber mit einer anständigen Verbindung sollte es ziemlich glatt sein.
quelle
In Bezug auf Verkehrsprobleme möchten Sie vermeiden, mehr als 20 bis 30 Pakete pro Sekunde und Peer zu senden. Wenn Sie kleinere, weniger Pakete senden, tritt im Allgemeinen eine (geringfügig) geringere Latenz und eine geringere Wahrscheinlichkeit für verworfene Pakete auf.
Sie möchten definitiv keine Updates mit einer Geschwindigkeit senden, die schneller als die Framerate ist, da die Spieler den Unterschied nicht erkennen können - in der Tat, wenn Sie nur 10-mal pro Sekunde Pakete senden und die Ergebnisse auf der Empfangsseite interpolieren / extrapolieren Die meisten Spieler werden keinen Unterschied bemerken.
quelle
Dies ist eine ziemlich breite Frage, aber ich werde versuchen, die wichtigen Aspekte zusammenzufassen.
Die erste Entscheidung im Netzwerkcode für Ihr Spiel ist, ob Sie eine Client / Server-Einrichtung einer Peer-to-Peer-Anordnung wünschen. Die meisten Spiele, wobei RTS wahrscheinlich die einzige bemerkenswerte Ausnahme ist, verwenden wahrscheinlich eine Client / Server-Architektur. Der Hauptvorteil besteht darin, dass diese Anordnung fehlertoleranter ist und mehr Kontrolle darüber bietet, welche Daten jeder Client empfängt. Peer-to-Peer ermöglicht das Senden von weitaus weniger Daten, erfordert jedoch, dass jeder Peer die Welt genau wie jeder andere Peer vollständig simuliert. Wenn ein Peer verzögert oder desynchronisiert, muss jeder entweder warten, bis er sich erholt hat, oder er geht einfach verloren.
UDP ist im Allgemeinen auch die richtige Wahl, sicherlich für jedes Client / Server-Modell. TCP mag für ein Peer-to-Peer-Spiel praktisch sein, aber selbst dann ist UDP möglicherweise die bessere Wahl. Grundsätzlich erledigt UDP weniger für Sie, was mehr Aufwand bedeutet, aber auch mehr Kontrolle darüber, wie Sie mit Fehlern umgehen.
Für Pong würde ich mich für Client / Server entscheiden, da es sich um ein aktionsorientiertes Spiel handelt. Eine Sache, die Sie hier beachten sollten, obwohl Sie sagen, dass ein Spieler "der Server" ist, strukturieren Sie Ihren Code am besten so, dass er im Wesentlichen einen lokalen Server ausführt und sich als Client mit ihm verbindet.
Sie möchten auf keinen Fall Updates in irgendeine Richtung "spammen". Pro Frame ist nur ein Update vom Server erforderlich, und Ihr Server sollte mit einer festen Framerate ausgeführt werden. Was das ist, liegt bei Ihnen, aber Sie müssen nicht über Bord gehen. Ein 50-ms-Frame (20 FPS) reicht aus, um ein reibungsloses Spiel zu erzielen. Um den Client reibungslos zu gestalten, möchten Sie die Interpolation verwenden. Der Client sollte ständig zwischen Server-Frame-Snapshots wechseln. Dies könnte jedoch leicht das Thema einer separaten Frage sein.
Client-Updates sollten ebenfalls begrenzt sein, obwohl eines pro Frame wahrscheinlich viel zu viel ist, wenn Ihr Client mit einer angemessenen Framerate ausgeführt wird.
quelle
Interessierst du dich für Betrug?
Wenn nicht, halbiert Peer-to-Peer Ihre Verzögerung, da es A <-> C anstelle von A <-> B <-> C ist. Wenn dies der Fall ist, sollten Sie aus Gründen der Fairness bei der Synchronisierung die Reaktion für den lokalen Spieler oder die meisten Spiele etwas verzögern. Lassen Sie den Spieler alles lokal tun und kehren Sie dann zurück, wenn das Ergebnis des Servers vom lokal simulierten abweicht.
Ein Pong-Klon ist eigentlich etwas knifflig, denn im Gegensatz zu den meisten Spielen kann man (als Entwickler) nicht schummeln, wenn eine Seite einen Treffer sieht und die andere nicht.
Was etwas Verallgemeinertes betrifft, so besteht eine Technik, von der ich gehört habe, die ich jedoch nicht für notwendig befunden habe (möglicherweise jedoch für Actionspiele), darin, Aktionen mit ihren tatsächlichen Zeitstempeln beizubehalten (Time-Ping empfangen / 2) und den Server zurücksetzen zu lassen ( snap), wenn ein früheres Ereignis eintritt, und wenden Sie spätere Aktionen erneut an. Auf diese Weise ist jeder lokal konsistent, es sei denn, es liegt ein Konflikt aufgrund der Interaktionen verschiedener Spieler vor. Die einzige Gefahr besteht in der Möglichkeit, die Zeit zurückzusetzen, wenn eine verzögerte Verbindung gefälscht wird.
quelle
Google Dead Reckoning. Das Versenden von Updates für 4 Spieler wird nicht von Bedeutung sein. Die Menge der gesendeten Daten wird in der Größenordnung von Bytes liegen. Das bedeutet, dass häufige Updates in Ordnung sein sollten. Mit Dead Reckoning bewegen Sie den Player auf dem Client und dem Server. Der Server ist die Autorität. Wenn die Position des Clients zu weit vom Server entfernt ist, muss sie wieder ausgerichtet werden. http://trac.bookofhook.com/bookofhook/trac.cgi/wiki/Quake3Networking Die Verwendung von UDP ist der richtige Weg. Bupdates werden häufig gesendet, damit verlorene Daten bald ohnehin durch eingehende Daten ersetzt werden. Die erneute Übertragung von Paketen von TCP lohnt sich nicht für die Position des Spielers. In diesem Artikel finden Sie weitere Informationen dazu, wie Sie Client und Server synchron halten können.
quelle
Ich habe vor ein paar Wochen ein 2-Spieler-Lokal-Netzwerk-Pong-Spiel programmiert. So habe ich es gemacht:
- Eine Seite öffnet einen Server, die andere stellt automatisch eine Verbindung her. - Beide spammen ihre Paddel x-Position mit 60 fps oder weniger [UDP] aufeinander zu. - Wenn eine Seite den Ball trifft, entscheiden sie über die neue Geschwindigkeit und Position des Balls und senden diese zum anderen [TCP] - wenn der Ball an einem Paddel vorbeifliegt, kontaktiert der Spieler, der ihn verpasst hat, den anderen mit einer Meldung zur Erhöhung der Punktzahl und der Ball wird zurückgesetzt [TCP] - der Ball wird die ganze Zeit unabhängig simuliert passt zur einfachen Ballphysik des Pong
Dies erzeugt ungefähr 0,3 bis 0,5 KByte / s Verkehr mit 60 fps und die Spieler haben keine Verzögerung in ihrer Wahrnehmung, sondern nur, wenn der Ping unter einem bestimmten Schwellenwert liegt, da die neue Position des Balls übertragen werden muss.
Auch Betrug ist mit diesem System einfach und es besteht eine hohe Wahrscheinlichkeit, dass die Synchronisation mit einer sehr verlustbehafteten Verbindung nicht mehr gewährleistet ist. Aber wen interessiert das Betrügen im Pong?!
quelle