RTS-Spielprotokoll


18

Ich habe über ein Multiplayer-RTS-Spiel nachgedacht. Der Teil, den ich nicht umgehen kann, ist die Synchronisation der Einheitenbewegungen. Wenn ich Einheit A auf XY stelle, muss ich dies dem Server mitteilen, der es an den anderen Client weiterleitet.

Ich bin gespannt, wie die Kommunikation aussehen würde. Möchten Sie dem Server nur mitteilen, dass ich die Einheit A von JZ nach XY verschiebe? Vielleicht müssen Sie stattdessen Bewegungskoordinaten kommunizieren? Was ist die effizienteste Methode, um die Bewegung von Einheiten von einem Client zum anderen zu kommunizieren?

BEARBEITEN

Dies ist eine neu gestellte Frage von Stackoverflow . Ich fand, dass diese Seite wahrscheinlich ein besserer Ort für die Frage war.

Eine der besseren Antworten aus diesem Beitrag:

Ich gehe davon aus, dass Sie beabsichtigen, das Client-Server-Netzwerk-Paradigma zu verwenden. In diesem Fall können Sie den Clients nicht vertrauen, dass sie die tatsächliche Positionierung der Einheiten vornehmen. Sie müssen diese Aufgabe an den Server delegieren. Anschließend nehmen Sie die Befehlsliste von jedem Client pro Tick und berechnen die Bewegung jeder Einheit. Sobald dies abgeschlossen ist, geben Sie mit dem nächsten Tick die Position jeder Einheit weiter, die für jeden Client relevant ist (entweder auf der Basis einer ganzen Karte oder Ansichtsbasis), und starten Sie den Vorgang erneut.


2
Die Antwort hängt wirklich davon ab, welche Methode Sie verwenden möchten. Client - Client oder Client - Server. Client zum Server ist einfacher, aber es erfordert einen vertrauenswürdigen Server
Cem Kalyoncu

Antworten:


25

Sie möchten nicht die Positionen aller Einheiten vom Server zu jedem Client synchronisieren. Das wird viel mehr Bandbreite in Anspruch nehmen, als Sie benötigen. Sie müssten sich auch mit dem Interpolieren / Extrapolieren von Einheitenpositionen usw. befassen. Fast keine professionellen RTS verwenden Client / Server!

Stattdessen möchten Sie nur die Befehle der Spieler senden. Anstatt die Einheiten sofort zu bewegen, wenn der Spieler darauf klickt, werden Sie den Befehl zum Verschieben, der zu einem späteren Zeitpunkt ausgeführt werden soll, in eine Warteschlange stellen - normalerweise nur ein paar Frames. Jeder sendet seine Befehle an alle. Ein paar Frames später führt jeder alle Befehle aus, und da das Spiel deterministisch ist, sehen alle das gleiche Ergebnis.

Der Nachteil ist, dass jeder Spieler so langsam ist wie der langsamste. Wenn jemand beim Aussenden von Befehlen ins Hintertreffen gerät, muss jeder langsamer werden und warten, bis er aufholt (in Starcraft 2 verlangsamt XXX das Spiel " dialog).


In der Tat gibt es noch eine weitere Sache, die normalerweise erledigt wird: den Server komplett ausschalten . Lassen Sie jeden Client seine Befehle an jeden anderen Client senden. Dies verringert die Verzögerung (anstatt eines Befehls von Ihnen -> Server -> Gegner, geht es nur von Ihnen -> Gegner) und erleichtert das Codieren, da Sie keinen separaten Server mehr codieren müssen. Diese Art von Architektur wird als Peer-to-Peer (P2P) bezeichnet.

Der Nachteil ist, dass Sie jetzt eine Möglichkeit zum Lösen von Konflikten benötigen. Da die Befehle der Spieler in den meisten Echtzeitstrategien jedoch unabhängig voneinander sind, ist dies normalerweise kein großes Problem. Außerdem skaliert es nicht gut - jedes Mal, wenn Sie einen neuen Spieler hinzufügen, muss jeder Spieler ihm seine Befehle senden. Sie werden kein MMO-RTS mit P2P erstellen.


Dieses Setup (nur das Senden von Befehlen über P2P) entspricht der Funktionsweise der meisten RTSs, einschließlich Starcraft, C & C und AoE, und ist die einzige Möglichkeit, mit der AoE möglicherweise 1500 Einheiten bei einer 28,8-kbps-Verbindung unterstützen kann .

(Bild der Vernetzung in AoE)

Hier einige weitere Tipps zum Schreiben eines P2P-RTS:

  • Aus offensichtlichen Gründen kann dieses Setup nur funktionieren, wenn Ihr Spiel eine Zeit mit festen Schritten verwendet - Sie möchten nicht, dass die Ergebnisse einer Berechnung von der Bildrate abhängen! Fixed-Step ist für die meisten Dinge einfacher zu handhaben, daher sollte dies kein Problem sein.
  • Damit dies funktioniert, müssen die Ergebnisse jedes Befehls vollständig deterministisch sein .
    • Dies ist normalerweise recht einfach, wenn Sie sich auf ein System beschränken (z. B. 32-Bit-Windows) und alle Clients zwingen, dieselbe ausführbare Datei zu verwenden: Stellen Sie sicher, dass alle Zufallszahlengeneratoren denselben Startwert haben und immer in derselben Reihenfolge aufgerufen werden. Seien Sie äußerst vorsichtig, wenn Sie ungeordnete Sammlungen durchlaufen . etc.
    • Dies ist äußerst schwierig, wenn Sie das Spiel plattformübergreifend spielen möchten oder (wie dies bei Linux häufig der Fall ist) den Clients erlauben möchten, den Code selbst zu kompilieren. Nicht nur verschiedene Systembibliotheken ziemlich garantiert sind verschiedene Implementierungen zu verwenden rand(), cos()etc., aber so ziemlich alle Gleitpunktarithmetik sind aus der Frage (siehe hier , hier und hier ) ! In diesem Fall ist es möglicherweise besser, Client-Server zu verwenden.
  • Du wirst alle Gerätepositionen einmal alle in eine Weile senden wollen, zumindest während des Debuggens, Desync Fehler zu erkennen (die, Vertrauen Sie mir, Sie werden haben). Ob Sie das im letzten Spiel behalten, liegt bei Ihnen - ich würde zumindest einige Einheiten synchronisieren (oder eine Art Prüfsumme verwenden), um versuchten Hacking zu entdecken.

Guter Post. Kleine Sache zum Hinzufügen, sogar die gleichen Compiler optimieren, debuggen / veröffentlichen und andere Flags können das Ergebnis verändern. Achtung!
Peter Ølsted

14

Ich habe ein TCP-vernetztes RTS erstellt, bei dem ich die Befehle selbst und nicht die Ergebnisse der Befehle übergeben habe . Zum Beispiel gibt ein Spieler einen Zugbefehl. Wenn der Verschiebungsauftrag für diesen Client gültig ist, wird er an den Server gesendet. Der Server sendet es dann an alle Clients zurück, die es validieren und ausführen.

Damit alle Client-Computer das Spiel selbst ausführen, akzeptiert der Server-Code Nachrichten und sendet sie an alle Clients zurück. Wenn ein Client einen Verschiebungsbefehl erteilt, wird er erst ausgeführt, wenn er vom Server zurückerhalten wird.

Der Server sendet eine 'Tick'-Nummer, an der auch der Befehl ausgeführt werden soll. Dies ist ein paar Ticks vor dem' aktuellen 'Tick. Auf diese Weise können alle Befehle auf allen Rechnern mit demselben Häkchen ausgeführt werden.

Ein Vorteil dieser Methode besteht darin, dass die Überprüfung des Befehls nicht von einem einzelnen Client-Computer abhängig ist. Wenn ich die Ergebnisse des Zuges bestanden habe, kann ich ihn möglicherweise hacken, um meine Einheiten schneller zu bewegen. Alle Clients müssen denselben Befehl ausführen, und wenn ein Computer ihn anders ausführt, ist dies offensichtlich.

Die Überprüfung des Befehls auf der Client-Seite vor dem Senden an den Server ist nicht erforderlich, spart jedoch theoretisch Netzwerkverkehr. Ich habe den gleichen Validierungscode verwendet, um der Benutzeroberfläche mitzuteilen, dass das Verschieben möglich ist, sodass kein zusätzlicher Code erforderlich ist.

Wie die Nachrichten aussehen könnten. Es ging mir nicht um Ultraeffizienz, da es mein erstes vernetztes Spiel war. Ich habe Befehle als Zeichenfolgen übergeben. Die Befehle würden folgendermaßen formatiert sein:"<player_id>:<command>:<parameters>"

Für ein konstruiertes Beispiel könnte ein Bewegungsbefehl wie folgt aussehen: "3:move:522:100:200". Dies bedeutet, dass der Spieler 3eine moveEinheit bilden möchte 522( 100, 200).

Der Server übergibt den Befehl an alle Kunden, einschließlich dem, der es geschickt, mit einem Häkchen Zahl wie folgt angebracht: "153238:3:move:522:100:200".

Dann würden alle Clients diesen Befehl ausführen, wenn Tick 153238 ausgeführt wird.


Ich habe der Frage ein bisschen mehr Info hinzugefügt. Die Antwort von SO scheint dem zu widersprechen, was Sie gesagt haben, und ich würde gerne die feineren Details besprechen.
Darthg8r

Ja, das ist ein anderer Weg, aber es scheint mir, dass es mehr Arbeit wäre, so viel vom Spielstatus herumzugeben, als nur die Befehle. Mein Spiel war so einfach, dass das Ganze auf jedem Client-Rechner laufen kann. Für ein MMO oder für etwas wie Minecraft wird nicht die gesamte Simulation auf der Clientseite ausgeführt, sodass Sie nur Informationen weitergeben, die für jeden Client einzeln relevant sind.
Philip
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.