Online Synchronisation

    Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

    • Online Synchronisation

      Liebe virtuelle Gemeinde,

      wie ihr vielleicht schon oft mitbekommen habt, versuche ich mich immer wieder an diversen Online-Multiplayer-Spielen (die dann immer in der Projekt-Kiste oder gar im Papierkorb landen :D ). Jetzt wollte ich mich mal allgemein bei euch erkundigen, meine Ideen euch präsentieren und um Hilfe und Kritik bitten.
      Hier geht es um die Synchronisation von Online-Spielen. Das bedeutet, dass es bei dem einen Spieler zwar nicht 100 % so aussehen muss wie bei einem anderen aber, dass alles flüssig läuft und es durch den Zeitunterschied keine Unterschiede bei den Einzelnen Spielern und dem Server gibt.

      Grundlegende Ideen:
      • Alles läuft über den Server, dieser verarbeitet das und benutzt die Daten auch weiter.
      • Es gibt eine Spielzeit, die bei jedem Ereignis vorausgeschickt wird, um die Zeitunterschiede auszugleichen (das wäre z.B. für MORPGs wichtig, Zauber und Fähigkeiten). Hier bräuchte ich ein wenig Hilfe, denn ich bin nicht sicher, ob ich hierfür current_time benutzten kann (GM6 - Unregelmäßigkeiten bei Zahlen). Alternativen bitte! ^^
      • Der Client schickt alle Bewegungs-Änderungen sofort an den Server, damit der gleich weiß, was Sache ist.
      • Der Client selbst soll auch die Bewegungen der anderen Spieler usw. flüssig umsetzten, auch wenn es mal laggen sollte.

      So, jetzt ist es natürlich wahrscheinlich, dass ich eine Menge vergessen habe, aber dafür ist das Ganze natürlich da. :whistling:
      Hier geht es erstmal nicht ums Praktische - also keine Codes, sondern nur rein ums Theoretische (aber auch Machbare).

      Ein fröhliches und konstruktives Diskutieren an alle! :D
      Gruß, euer kopierjunge
    • Ich sehe da 2 Möglichkeiten der Bewegung, einmal spielt es sich lag frei, einmal nicht.

      Lagfrei
      Die idee ist wohl das, was auch großen MMORPGs wie WoW oder EQ2 benutzt wird. Wenn der Client1 los läuft wird die Bewegung an den Server gesendet und dieser sendet dann die Bewegung an die Clienten2 und 3 weiter.
      Das Resultat ist, das bei Client2 und 3 der Spieler vom Clienten1 verzögert losläuft und verzögert stoppt.
      Gibt den Effekt das wenn alle gleichzeitig loslaufen jeder denkt, er wäre der erste.

      Nicht-Lagfreie Variante
      Die idee ist, jede Bewegung die ein Spieler macht, erst zum Server zu schicken, dieser schickt dann an jeden Clienten die Bewegungsänderung, auch an den, der die Änderung ausgefressen hat.
      Vorteil: Jeder Spieler, vorrausgesetzt sie haben alle die gleiche Verzögerung zum Server, bekommen gleichzeitig die Bewegungsänderung mit und der Spieler läuft bei allen gleichzeitig los.
      Nachteil: Wenn ein Spieler auf laufen drückt dauert es erst einen Moment bis sich die Spielfigur bewegt. Das ist in manchen Situationen tötlich und unakzeptabel.


      Nun, da haben wir den Punkt, das die Lagfreie Variante wohl die bessere Lösung ist, weil ich teilweise mit der 39dll eine Verzögerung von sagenhaften viertelsekunden (250 ms) habe, was wiederum heisst, von Client zu Client wären das 500 ms, also eine ganze halbe sekunde.

      Nun da kommen wir zu einem dicken Problem was die Kollision betrifft. Wo soll sie stattfinden? Wenn ich mit einer Spielfigur herumlaufe sollten möglichst auch die Geschosse mir leben abziehen die mich Visuell treffen. Wobei das Problem besteht, wenn Client1 auf Client2 schiesst, schiesst er in die Richtung von Client2. Da die Kugeln aber eine halbe Sekunde später erst bei Client2 ankommen, würde Client1 sehen das er trifft, aber bei Client2 kann durch die halbe Sekunde Verzögerung locker ausweichen. Was also tun?


      Die Lösung muss irgendwo mit der Einberechnung der Verzögerung liegen, allerdings wo und wie das weis ich noch nicht.

      Bei Shootern wie Half-Life2 hat man leider nur Verzögerungen von ganzen 50 ms, was ein zehntel einer Sekunde ausmacht, das fällt nicht auf, wohl aber bei einer halben Sekunde.
      Wobei dort auch das Problem ist, dass man sich teilweise schon hinter einer Mauer zurückgezogen hat und trotzdem erschossen wird. Client zu Client lag.
    • Ich kenne das! ich mach auch viele online Spiele und so was! (gerade kam ein Spruch! Ich weiß nicht ob man das so raus hört aber mit "und so was" WILL ICH NICHT copyboys Online Spiele als was anders oder so darstellen!)

      Ich hab mich mal an PingPong versucht!
      Eigentlich leicht! Aber ich wollte nchit jeden Step Daten versenden!
      Also: Er sendet wenn die Taste gedrückt wurde die position und die bewegungs richtung! Das gleiche beim stopen!
      Es ging aber total schief! Das Spiel war so schlecht synchronisiert! Das lag daran das es ein schnelle speil war! Bei einen langsamen Spiel fählt das nciht so auf!

      Ich versuche um eine kleine verzögerung hinzubekommen immer möglichst wenige Nachrichten los zusenden!

      Man könnte ja die Zeit mit (wie du sagtes) current_time berechnen und so z.b. den Player berechnen lassen wie lange die daten brauchen bis sie auf den server sind!
      Nun läuft der Player langsamer! Er berechnet (angenommen ein Schritt braucht 4 Stepts Speed ist auch 4 also eine weite von 16 Pixel) nun wie lange er zusätlich braucht!
      Ich musste die Berechnung noch testen ausm Kopf könnte ich die nicht!

      Effekt: Der Player startet zwar früher, ist aber genau so schnell am Ziel wie die andern!

      Soll ich das mal machen hab eh nix zu tun?

      PS: So wie da hab ich das noch nie gemacht ist aber ne Idee!

      Achja! das ist nur möglich wenn die Weite eines Schrittes bekannt ist!

      EDIT: Code ist fertig: (war nicht so schwer)

      GML-Quellcode

      1. time = argument0/argument1;
      2. time += global.ping_time/1000*fps;
      3. speed = argument0/time;



      argument0 ist die Weite (also z.B. 32 Pixel)
      argument1 ist der Speed (hier kann man auch speed nehmen z.B. 4 Pixel pro Step)
      time berechnet die Zeit die er braucht, amanfang die normale.
      Dann kommt noch die anzahl der Steps, die das Spiel braucht, bis der Server die Daten verarbeitet hat dazu.
      speed wird also wieder weite pro zeit

      global.ping_time ist Zeit, die das Spiel braucht, bis der Server die Daten verarbeitet hat.
      Sie wird wie folg ausgerechnet:

      Der Client Sendet ein Befehl (was weiß ich) "Ping" an den Server.
      und speicher sich die Zeit (global.ping_ask = current_time)
      Der Server antwortet sobalt er "Ping" bekommen hat "Pong".
      Sobalt der der Client "Pong" erhalten hat, zieht er die Differenz (global.ping_time = current_time - global.ping_ask)

      Und fertig ist Die Zeit!
      „Zwei Dinge sind unendlich, das Universum und die menschliche Dummheit, aber bei dem Universum bin ich mir noch nicht ganz sicher.“
      Albert Einstein

      Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von dave ()

    • Die Idee mit der gametime ist, dass alle Aktionen, die eine Weile brauchen um ausgeführt werden zu können (z.B. Zauber) früher den Clients mitgeteilt werden mit der exakten Zeit, damit dieser schon weiß, wann es losgeht (und das ganze auch noch grafisch anzeigen kann ^^ ).

      @ Dur'Rean: Mir wäre eine leichte Verzögerung bei der Bewegung spielerisch gar nicht mal so unrecht. Es wäre nicht sonderlich schlimm, wenn ich 200ms brauche, um vom Stand in Bewegung zu kommen :D

      @ dave: Ich hab noch nicht verstanden, wofür das jetzt gut sein soll 8| :)
      Das mit der Bewegung ist wirklich sehr kompliziert. Zumal es ja nicht nur im ein PingPong-Spiel geht, sondern (in meinem Fall) um ein Sideview-Game. Nur wenn man es einmal gepackt hat, hat man es hinter sich und das ist das Gute :D
    • Egal! Bei sideview fürde das eh net gehen! aber ich hatte noch ne idee die ich vergessen hab^^
      Egal!
      „Zwei Dinge sind unendlich, das Universum und die menschliche Dummheit, aber bei dem Universum bin ich mir noch nicht ganz sicher.“
      Albert Einstein
    • Um das Problem mit current_time zu klären:

      Es gibt eine HiRes dll die die Zeit um ein vielfaches genauer berechnet als die Funktionen des GameMaker.
      Hier ist der Link dazu:

      gmc.yoyogames.com/index.php?showtopic=109752
    • Wow! Super dll!
      Ich hab mal ein vergleich gemacht!
      die Dll zeigt an das der PC 6Sek länger an ist als current_time! :D
      Also schon ein großer Unterschied!
      Danke!
      „Zwei Dinge sind unendlich, das Universum und die menschliche Dummheit, aber bei dem Universum bin ich mir noch nicht ganz sicher.“
      Albert Einstein
    • So, ich muss jetzt doch noch einmal nachhaken, weil ich selbst wirklich nicht weiterweiß. :D
      dave hatte es schon so in etwa gesagt:
      Ich hab mich mal an PingPong versucht!
      Eigentlich leicht! Aber ich wollte nchit jeden Step Daten versenden!
      Also: Er sendet wenn die Taste gedrückt wurde die position und die bewegungs richtung! Das gleiche beim stopen!
      Es ging aber total schief! Das Spiel war so schlecht synchronisiert! Das lag daran das es ein schnelle speil war! Bei einen langsamen Spiel fählt das nciht so auf!
      Das war aber nur ein Pong-Spiel, stellt euch das mal bei einem Jump&Run vor! 8|

      Also die eigentliche Frage jetzt lautet: Wie bewege ich bei einem Jump&Run die anderen Spieler ohne "hässliche Aussetzer"?
      Hässliche Aussetzter = Die Spieler springen mit einem Hopps zu stellen, wenn sie die Richtung ändern.

      Das Spiel soll gleichzeitig flüssig aussehen und trotzdem etwas synchroner laufen als ohne die "Modifikationen".
      So soll z.B. auch bei einem Spieler der lagt die Spielfigur stehenbleiben, weil sie keine Daten bekommt.

      Ich versuche mich mal an einer Umsetzung, derweil würde ich hier gern über weitere Schritte diskutieren ^^

      Gruß, euer kopierjunge
    • Nunja. Ohne diese "Aussetzer" und dennoch präzise musst du mit den X und Y Koordinaten arbeiten. Aber nicht so, dass der Spieler gleich an der Stelle erscheint, sondern sich zu dem neuen Punkt von dem, an dem er sich jetzt befindet, ganz normal hinbewegt, wie wenn er lokal gesteuert werden würde. Damit sieht das ganze flüssig und runder im Bewegungsablauf aus.
      Du erzeugst damit aber unsichtbare Lags, zu sehen auch in manchen Online Ego Shootern. Da treffen beispielsweise zwei Spieler aufeinander, Spieler 1 schießt und trifft Spieler 2, Spieler 2 schießt für Spieler 1 subjektiv kurz nach dem eigenen Schuß, dennoch ist Spieler 1 tot. Das liegt dann daran, dass für den Server die Information zählt, die am schnellsten beim Server ist. Auch wenn es nicht die gleiche ist, die du am Client gerade auf dem Bildschirm hast, was dadurch entsteht, dass die Bewegungsabläufe und Richtungen eben zwischen den Datenübertragungen nur grob geschätzt werden können.
      "Die Erde ist ein Irrenhaus. Dabei könnte das bis heute erreichte Wissen der Menschheit aus ihr ein Paradies machen. Dafür müsste die weltweite Gesellschaft allerdings zur Vernunft kommen."
      - Joseph Weizenbaum
    • In der Beta vom MMORPG Age of Conan gabs es manchmal ewig lange Lags, während dessen man sich absolut nicht bewegen konnte ->
      Wurde also so gelöst, dass alles vom Server aus geregelt wurde und dieser den Input erhielt, verarbeitete und die neuen Daten zurücksendete... Das ist zwar auch nichts Neues...
      Die Spieler springen mit einem Hopps zu stellen, wenn sie die Richtung ändern.

      ..Aber ich versteh den Satz irgendwie nicht ganz.. :(
      "das war meine letzte flamewar PM an dich ."
    • Ganz genau muss es wirklich nicht sein, ich bin (leider) ganz irre auf den Part mit dem "gut Aussehen".
      Außerdem komme ich mit dem Coden nicht so recht weiter, weil ich mich nicht entscheiden kann/mir nicht einfällt, wie ich es jetzt eigentlich anpacken soll.. :S

      @blubberblub: Ich wollte das eigentlich erst weiter umschreiben, habs aber gelassen, weil die, die sich mit der Materie auskennen, eigentlich wissen sollten, was ich damit meine ^^ Gemeint ist, wenn die Latenz (Zeit, die eine Message [von einer bestimmten Größe] von einem Ort zu einem anderen im Internet braucht) zwischen 2 Spielern sich ändert, dass Spieler A weiter läuft, weil bei Spieler B die Message noch nicht angekommen ist und dann (von Spieler B aus gesehen) Spieler A bei Empfang der Message zu der Stelle springt, an der er sich umgedreht hat.
    • Also, bei mir spielen die Latenzen keine große Rolle. Ich hab allerdings dafür auch den room_speed aufgedreht und entsprechend den Haken bei "synchronize to avoid tearing" weggemacht, was etwas nervt.
      Ich habe eher ein Problem mit Kollisionen, allerdings geht es bei mir um ein RTS, und ich habe mich erstmal für Client-Client entschieden, weil ich nicht hunderte von Einheiten auf einem Rechner haben will. Trotzdem nehme ich an, daß auch in Deinem Fall (Host-Client) keine wirkliche Kompensation von Latenzen nötig ist, sondern es reicht wenn die Bewegungen auf dem Client etwas geglättet werden.

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Melancor ()

    • .. sondern es reicht wenn die Bewegungen auf dem Client etwas geglättet werden.

      Genau das versuch ich ständig zu sagen, danke für die Formulierung :D
      Ich hab nur keine Ahnung, wie ich das am Sinnvollsten anstelle. Und da es sich blöderweise um ein Jump&Run handelt, wird das ziemlich kompliziert und da will ich ungern fünf, sechs mal alles umschreiben müssen. Nachrichten sollen ja kompakt sein, und es sollen so wenige wie möglich gesendet werden.