
Im Mai dieses Jahres nahm ich als Spieler an teil. Ich bemerkte, dass, sobald die Anzahl der Spieler eine bestimmte Zahl erreicht, einige von ihnen alle paar Minuten âabfallenâ. Leider fĂŒr Sie (aber nicht fĂŒr mich) war ich einer der Spieler, die sich jeden Mal verabschiedeten auch bei stabiler Verbindung. Ich nahm dies als persönliche Herausforderung und begann, nach den Ursachen des Problems zu suchen. Nach drei Wochen Debugging, Tests und Korrekturen war der Fehler schlieĂlich behoben, aber diese Reise war alles andere als einfach., selbst bei einer guten Verbindung. Ich habe das als persönliche Herausforderung angesehen und begonnen, nach den Ursachen des Problems zu suchen. Nach drei Wochen des Debuggings, Testens und Fehlersuchens war der Fehler schlieĂlich behoben, aber diese Reise war alles andere als einfach.
Die Probleme in Mehrspieler-Spielen sind sehr schwer nachzuvollziehen. Sie treten oft unter sehr spezifischen Netzwerkkonfigurationen und ZustĂ€nden im Spiel auf (in diesem Fall â mit mehr als 200 Spielern). Selbst wenn es gelingt, das Problem nachzustellen, kann es nicht richtig debuggt werden, da das Setzen von Kontrollpunkten das Spiel stoppt, die Timer verwirrt und in der Regel zu einer Unterbrechung der Verbindung aufgrund von Timeout fĂŒhrt. Aber dank HartnĂ€ckigkeit und eines groĂartigen Tools namens , konnte ich herausfinden, was wirklich passiert.
Kurz gesagt: Aufgrund eines Fehlers und einer unvollstĂ€ndigen Implementierung der Verzögerungssimulation befand sich der Kunde manchmal in der Situation, dass er in einem einzigen Takt ein Netzwerkpaket mit etwa 400 Aktionen von SpielentitĂ€ten (wir nennen es "Megapaket") senden musste. Danach muss der Server nicht nur alle diese Eingabewertungen korrekt empfangen, sondern sie auch an alle anderen Kunden senden. Wenn du 200 Kunden hast, wird das schnell zum Problem. Der Kanal zum Server wird schnell ĂŒberlastet, was zu Paketverlusten und einem Kaskadeneffekt an wiederholt angeforderten Paketen fĂŒhrt. Die Verzögerung der Eingabewertungen fĂŒhrt dann dazu, dass noch mehr Kunden beginnen, Megapakete zu senden, und die Lawine wird noch gröĂer. GlĂŒckliche Kunden schaffen es, sich zu erholen, wĂ€hrend alle anderen "ausfallen".

Das Problem war ziemlich grundlegend, und ich habe zwei Wochen gebraucht, um es zu beheben. Es ist recht technisch, daher werde ich im Folgenden die technischen Einzelheiten erlĂ€utern. Aber zunĂ€chst sollten Sie wissen, dass ab Version 0.17.54, die am 4. Juni veröffentlicht wurde, der Multiplayer unter Bedingungen mit temporĂ€ren Verbindungsproblemen stabiler geworden ist, und die Verzögerungsreduzierung deutlich weniger fehleranfĂ€llig ist (weniger Ruckler und Teleportationen). AuĂerdem habe ich die Methode zur Reduzierung von Verzögerungen im Spiel geĂ€ndert und hoffe, dass sie dadurch etwas flĂŒssiger werden.
Multiplayer-Megapaket â technische Einzelheiten
Einfach ausgedrĂŒckt funktioniert der Multiplayer im Spiel folgendermaĂen: Alle Clients simulieren den Spielzustand, indem sie nur die Eingaben der Spieler empfangen und senden (genannt âInput Actionsâ Input Actions). Die Hauptaufgabe des Servers besteht darin, sicherzustellen Input Actions und zu steuern, dass alle Clients in einem Takt die gleichen Aktionen ausfĂŒhren. Mehr dazu können Sie im Post lesen .
Da der Server Entscheidungen treffen muss, welche Aktionen ausgefĂŒhrt werden sollen, verlaufen die Aktionen des Spielers in etwa folgender Reihenfolge: Aktion des Spielers -> Spielclient -> Netzwerk -> Server -> Netzwerk -> Spielclient. Das bedeutet, dass jede Aktion des Spielers erst ausgefĂŒhrt wird, nachdem sie den Hin- und RĂŒckweg ĂŒber das Netzwerk zurĂŒckgelegt hat. Dadurch wĂŒrde das Spiel extrem langsam erscheinen; daher wurde fast sofort nach der EinfĂŒhrung des Mehrspielermodus ein Mechanismus zur Verborgenen Verzögerung implementiert. Die Verborgene Verzögerung emuliert die Eingabe des Spielers, ohne die Aktionen anderer Spieler und Entscheidungen des Servers zu berĂŒcksichtigen.

In Factorio gibt es einen Spielzustand Spielzustand â das vollstĂ€ndige Zustand der Karte, des Spielers, der EntitĂ€ten und aller anderen Elemente. Er wird deterministisch in allen Clients simuliert, basierend auf den vom Server empfangenen Aktionen. Der Spielzustand ist heilig, und wenn er jemals von dem Server oder einem anderen Client abweicht, entsteht eine Desynchronisation.
ZusÀtzlich Spielzustand wir haben einen Zustand der Verzögerung Verzögerungszustand. Er enthÀlt eine kleine Teilmenge des Hauptzustands. Verzögerungszustand es ist nicht heilig und stellt einfach dar, wie der Zustand des Spiels in Zukunft aussehen wird, basierend auf den Eingaben der Spieler. Input Actions.
DafĂŒr speichern wir eine Kopie der erstellten Input Actions in der Verzögerungswarteschlange.

Das heiĂt, am Ende des Prozesses sieht das Bild auf der Clientseite ungefĂ€hr so aus:
- Wir wenden an Input Actions alle Spieler auf Spielzustand so, wie diese Eingabeschnitte vom Server empfangen wurden.
- Wir entfernen aus der Verzögerungswarteschlange alle Input Actions, die laut Server bereits auf Spielzustand.
- Entfernen Verzögerungszustand angewendet wurden, und setzen es zurĂŒck, damit es genau so aussieht wie Spielzustand.
- Wir wenden alle Aktionen aus der Verzögerungswarteschlange auf Verzögerungszustand.
- Basierend auf den Daten Spielzustand und Verzögerungszustand rendern wir das Spiel fĂŒr den Spieler.
Das alles wird in jedem Takt wiederholt.
Zu kompliziert? Entspannen Sie sich nicht, das ist noch nicht alles. Um die UnzuverlÀssigkeit von Internetverbindungen auszugleichen, haben wir zwei Mechanismen entwickelt:
- Verpasste Takte: wenn der Server entscheidet, dass Input Actions im Spieltakt ausgefĂŒhrt werden, und wenn er keinen Input Actions Spieler erhalten hat (zum Beispiel wegen erhöhter Verzögerung), wird er nicht warten, sondern diesem Client mitteilen: âIch habe deine Input Actions, ich werde versuchen, sie im nĂ€chsten Takt hinzuzufĂŒgen." Dies wurde so gemacht, damit wegen Verbindungsproblemen (oder Computerproblemen) eines Spielers die Kartenaktualisierung fĂŒr alle anderen nicht verlangsamt wird. Es ist erwĂ€hnenswert, dass Input Actions nicht ignoriert, sondern einfach nur aufgeschoben werden.
- Die Verzögerung der Hin- und RĂŒckreise: Der Server versucht abzuschĂ€tzen, wie hoch die Round-Trip-Verzögerung zwischen dem Client und dem Server fĂŒr jeden Client ist. Alle 5 Sekunden bespricht er gegebenenfalls mit dem Client die neue Verzögerung (abhĂ€ngig davon, wie die Verbindung in der Vergangenheit funktioniert hat) und passt die Round-Trip-Verzögerung entsprechend an.
Diese Mechanismen sind fĂŒr sich genommen recht einfach, aber wenn sie gemeinsam verwendet werden (was oft bei Verbindungsproblemen passiert), wird die Logik des Codes schwer kontrollierbar und hat viele RandfĂ€lle. DarĂŒber hinaus mĂŒssen Server und Verzugsschlangen diese speziellen Mechanismen richtig implementieren. EingabemaĂnahme mit dem Namen BewegeStoppImNĂ€chstenTick. Dadurch lĂ€uft der Charakter bei Verbindungsproblemen nicht von selbst (zum Beispiel unter einen Zug).
Jetzt mĂŒssen wir Ihnen erklĂ€ren, wie die Auswahl von EntitĂ€ten funktioniert. Einer der ĂŒbermittelten Typen EingabemaĂnahme ist die VerĂ€nderung des Auswahlzustands einer EntitĂ€t. Dies informiert alle darĂŒber, auf welche EntitĂ€t der Spieler den Mauszeiger bewegt hat. Wie Sie verstehen können, handelt es sich hierbei um eine der hĂ€ufigsten EingabemaĂnahmen, die von den Clients gesendet werden. Daher haben wir es optimiert, um die Bandbreite zu schonen und so wenig Platz wie möglich einzunehmen. Dies wurde so umgesetzt: Bei der Auswahl jeder EntitĂ€t speichert das Spiel anstelle von absoluten, hochprĂ€zisen Kartenvorgaben eine niedrigprĂ€zise relative Verschiebung im Vergleich zur vorherigen Auswahl. Das funktioniert gut, weil die Mausmarkierung normalerweise sehr nah an der vorherigen Auswahl erfolgt. Dadurch ergeben sich zwei wichtige Anforderungen: Input Actions dass niemals etwas ĂŒbersprungen werden darf und dass sie in der richtigen Reihenfolge ausgefĂŒhrt werden mĂŒssen. Diese Anforderungen werden erfĂŒllt fĂŒr Spielzustand. Aber da die Aufgabe Latency state darum geht, fĂŒr den Spieler "ausreichend gut auszusehen", werden in den LatenzzustĂ€nden diese Anforderungen nicht erfĂŒllt. Verzögerungszustand berĂŒcksichtigt , die mit TaktĂŒberschreitungen und Ănderungen der Hin- und Retourlatenzen verbunden sind.
Sie können sich wahrscheinlich schon vorstellen, wohin das fĂŒhrt. Endlich beginnen wir, die Ursachen des Megapakets zu erkennen. Das Grundproblem liegt darin, dass die Entscheidungslogik, ob eine Handlung der Ănderungswahl ĂŒbergeben werden soll, auf Verzögerungszustand, und dieser Zustand enthĂ€lt nicht immer die richtigen Informationen. Daher wird das Megapaket ungefĂ€hr so generiert:
- Der Spieler hat Verbindungsprobleme.
- Es kommen Mechanismen zur TaktĂŒberspringung und zur Regelung der Hin- und RĂŒckverzögerung ins Spiel.
- Die Warteschlange der VerzögerungszustĂ€nde berĂŒcksichtigt diese Mechanismen nicht. Das fĂŒhrt dazu, dass einige Aktionen vorzeitig entfernt oder in der falschen Reihenfolge ausgefĂŒhrt werden, was zu falschen Verzögerungszustand.
- Der Spieler hat seine Verbindungsprobleme nicht mehr und simuliert, um den Server einzuholen, bis zu 400 Takte.
- In jedem Takt wird eine neue Handlung zur Ănderung der EntitĂ€tswahl generiert und zur Sendung an den Server vorbereitet.
- Der Client sendet dem Server ein Megapaket von ĂŒber 400 Ănderungen der EntitĂ€tswahl (und auch andere Aktionen wie Schuss- und GehzustĂ€nde waren von diesem Problem betroffen).
- Der Server erhĂ€lt 400 Eingabeaktionen. Da ihm nicht gestattet ist, auch nur eine einzige Eingabeaktion zu ĂŒberspringen, verlangt er von allen Clients, diese Aktionen auszufĂŒhren und sie ĂŒber das Netzwerk zu senden.
Die Ironie besteht darin, dass der Mechanismus, der zur Einsparung der Bandbreite des Kanals gedacht war, in der Folge riesige Netzwerkpakete erzeugte.
Wir haben dieses Problem gelöst, indem wir alle RandfĂ€lle bei der Aktualisierung und der UnterstĂŒtzung der Verzögerungsschlange behoben haben. Obwohl dies ziemlich viel Zeit in Anspruch nahm, war es letzten Endes besser, alles richtig umzusetzen, als sich auf schnelle Hacks zu verlassen.
Quelle: habr.com
