Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

22.10.2014, 19:25

Problematik von Real-time Multiplayer Spielen

Liebe Community,

ich bin gerade dabei für mein Studium ein Multiplayer-Spiel zu programmieren. Das Spiel besteht aus verschiedenen Spielern, die sich als Panzer gegeneinander abschiessen. Das ganze ist im Top Down gehalten. Ich benutze als Programmiersprache Java mit Libgdx und für das ganze Networking die Lib Kryonet.
Diese ermöglicht mir relativ einfach event-basiert Anfragen entgegenzunehmen und zu verarbeiten. Das Spiel an sich steht schon, jedoch fehlt noch der Multiplayer-Part.

Noch was zur überlegten Architektur und zu den Anforderungen. Ich möchte gerne das Spiel als Client-Server realisieren wobei jeder ein Host sein kann und die anderen Joinen (das steht schon). Unterstützende Technologie sollte dabei TCP sein. Da das Spiel NUR im LAN einigermassen flüssig laufen soll, verzichte ich auf den Gebrauch von UDP. Das sollte meiner Meinung reichen, da man im LAN ziemlich niedrige Latenzen hat.

Was ich schon habe: Der Host kann schon einen Server starten und die anderen können joinen. Dies wird auch bei allen korrekt dargestellt. Das Problem ist jetzt nun der eigentliche Austausch von Daten. Im Moment ist es jetzt so, dass ich als Client meine Aktion an den Server schicke (bewege nach rechts). Der Server reagiert event-basiert (Listener) auf die Nachricht, verschiebt den Spieler um die gewünschte Position und teilt dies allen Clients mit.
Dies ruckelt ziemlich stark und ich glaube das liegt an der event-basierten Logik. Was ich im Internet gefunden habe ist, dass man am besten ein FIFO Konstrukt verwenden soll und sobald eine Nachricht eintrifft, diese in die Warteschlange befördert. Parallel habe ich auf dem Server eine eigene Game-Loop, die jedes mal die erste Nachricht herauspickt und sie verarbeitet und allen Clients bescheid gibt, was sich geändert hat.
Btw. verschickt werden eigentlich ziemlich kleine Pakete mit Id des Spielers und den Koordinaten(x, y).

Ich hab mich versucht in die ganze Problematik einzuarbeiten mit Prediction, Interpolation usw. jedoch komme ich nicht auf einen grünen Zweig. Was mir wirklich helfen würde, wäre ein Codeschnipsel, der genau diese Problematik löst.

Nun zu meinen eigentlichen Fragen:
- Wäre das mit der Warteschlange ein guter Weg?
- Ist das der Fehler, der mein Spiel so ruckeln lässt? (wahrscheinlich wird da der Thread des Listeners blockiert, während ich am verarbeiten bin..)
- Ist im LAN Prediction und Interpolation überhaupt nötig?

Ich hoffe irgendwer kann mir helfen..


mfg

timi19

2

22.10.2014, 19:45

Zitat

ich glaube

An dieser Stelle kann ich nur sagen: Nicht glauben sondern prüfen :D

Ein Problem bei deinem Design könnte das TCP sein, ich habe gehört, dass in zeitkritischen (quasi Echtzeit-)Systemen (auch innerhalb von LAN) UDP verwendet wird, da TCP-Pakete dazu neigen, sich zu verzögern, da Netzwerkgeräte viele kleine Pakete sammeln und diese dann gleichzeitig weiterverschickt.

Um das zu erkennen würde ich mir mal mit wireshark den Netzwerkverkehr anschauen, insbesondere die 1. Spalte mit den Zeiten.

Des weiteren würde ich mal im Cliet den Ping mitschreiben (nimm eine LogDatei dazu, dann kannst du einfacher analysieren), also wie viel Zeit zwischen dem Melden der aktualisierten Position an den Server und dessen Update an alle Spiele vergeht. Anhand dieser Zeit kannst du dann abschätzen, in wieweit du "schummeln" musst.
Falls hier Werte von <15ms auftreten lohen sich Interpolationen nicht, das entspricht etwa 60Hz, was fps-Rate entsprechen dürfte.

Bei Werten < 50ms würde ich erst einmal die Interpolation zwischen den beiden empfangenen Punkten einbauen. Damit hängst du zwar immer ein bisschen hinterher, der Effekt sollte aber nicht wirklich stören, da sich ein Panzer innerhalb von 50ms sicherlich nur sehr wenig bewegt.

Ab Bereichen von 100ms bis 200ms kann eine Vorhersage Sinn machen, da die Werte ansonsten merklich verzögert auf dem Bildschirm erscheinen.

Stazer

Alter Hase

Beiträge: 468

Wohnort: Berlin

Beruf: Student

  • Private Nachricht senden

3

23.10.2014, 04:48

Im lokalen Netzwerk ist es eigentlich nicht nötig zu interpolieren, da hier die Latenzen sehr niedrig sind.
Probiere es am Besten aus. Übrigens, nur weil UDP schneller ist als TCP würde ich es nicht unbedingt verwenden, denn
TCP ist weitaus reliabler als UDP. Das es gut funktioniert zeigen Spiele wie World of Warcraft oder Minecraft.

Freundliche Grüße
Stazer

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

4

23.10.2014, 07:19

Wie immer gilt: Erst die einfache Version zum Laufen bringen und dann die Performance evaluieren.
Das heißt konkret:
- Benutz TCP
- Mach keine Interpolation oder Prediction
- Mach keine Warteschlange, sondern arbeite die Pakete direkt ab

Auch ohne diese Dinge ist die Aufgabe schon umfangreich genug. Wenn Du das aber erfolgreich umsetzen kannst und das Spiel damit läuft (also man kann wirklich schon richtig mit anderen spielen!), dann kannst Du wie gesagt noch immer schauen, ob es Punkte zur Optimierung gibt und ob diese notwendig sind.

Erst Probleme konkret feststellen und dann optimieren. Das gilt generell für jedes Projekt.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

5

23.10.2014, 07:46

Ich gebe BlueCobold recht, allerdings ist ein nachträgliches Einbauen solcher Features nicht einfach. Darum macht es schon Sinn, sich vorher Gedanken darüber zu machen, ob man sowas benötigen wird oder nicht, und dann sein Software-Design direkt dementsprechend flexibel zu gestalten.

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

6

23.10.2014, 07:58

Flexibel genug sollte man seine Software immer gestalten.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

7

26.10.2014, 16:50

So, der Server steht, Clients können sich verbinden und es wird bei allen Clients alles richtig angezeigt. Desweiteren funktioniert auch die Kollisionserkennung.
Der nächste Schritt ist nun der Schuss von den Panzern.
Ich überlegte mir, wie beim steuern, dass ich einfach den "Command" an den Server schicke und der macht einfach alles. Der Unterschied zum einfachen Positionsaustausch ist ja nun, dass der Spieler einmal die Leertaste drückt und sonst nichts mehr bzw. den Rest macht der Server.
Meine Frage hier ist, ob ich jetzt eine Server-Game-Loop brauche..?
Der Server bekommt die Nachricht, dass ein Schuss abgefeuert wurde und muss nun eine Zeit land die Position des Schusses berechnen und allen Clients mitteilen.

Wie gehe ich hier am besten vor?
Eine einfache Game-Loop mit Thread.sleep(...)? Sozusagen mit einem fixen Time-Step (60 FPS)? Oder die Berechnung der Schuss-Trajektorie dem Client lassen?

Danke schonmal für eure Hilfe:)

Werbeanzeige