Megapack: Wie Factorio das 200-Spieler-Multiplayer-Problem löste

Megapack: Wie Factorio das 200-Spieler-Multiplayer-Problem löste
Im Mai dieses Jahres habe ich als Spieler teilgenommen KatherineOfSky MMO-Events. Mir ist aufgefallen, dass, wenn die Anzahl der Spieler eine bestimmte Anzahl erreicht, alle paar Minuten einige von ihnen „abfallen“. Zum Glück für Sie (aber nicht für mich) war ich einer dieser Spieler jedes Malauch bei guter Verbindung. Ich nahm es als persönliche Herausforderung und begann, nach den Ursachen des Problems zu suchen. Nach drei Wochen des Debuggens, Testens und Behebens ist der Fehler endlich behoben, aber der Weg war nicht ganz einfach.

Probleme in Multiplayer-Spielen sind sehr schwer aufzuspüren. Sie treten normalerweise unter ganz bestimmten Netzwerkparametern und unter ganz bestimmten Spielzuständen auf (in diesem Fall über 200 Spieler). Und selbst wenn ein Problem reproduziert werden kann, kann es nicht ordnungsgemäß debuggt werden, da das Einfügen von Haltepunkten das Spiel stoppt, die Timer durcheinander bringt und normalerweise dazu führt, dass die Verbindung aufgrund einer Zeitüberschreitung abbricht. Aber dank Ausdauer und einem wunderbaren Werkzeug namens ungeschickt Ich konnte herausfinden, was los ist.

Kurz gesagt, aufgrund eines Fehlers und einer unvollständigen Implementierung der Verzögerungszustandssimulation befand sich der Client manchmal in einer Situation, in der er in einem Taktzyklus ein Netzwerkpaket senden musste, das aus Spielereingabeaktionen zur Auswahl von etwa 400 Spieleinheiten bestand ( wir nennen es ein „Megapaket“). Danach muss der Server alle diese Eingabeaktionen nicht nur korrekt empfangen, sondern sie auch an alle anderen Clients senden. Bei 200 Kunden wird das schnell zum Problem. Der Kanal zum Server verstopft schnell, was zu Paketverlusten und einer Kaskade erneut angeforderter Pakete führt. Das Aufschieben von Eingabeaktionen führt dann dazu, dass mehr Clients anfangen, Megapakete zu versenden, und ihre Lawine wird noch stärker. Erfolgreiche Kunden schaffen es, sich zu erholen, alle anderen fallen ab.

Megapack: Wie Factorio das 200-Spieler-Multiplayer-Problem löste
Das Problem war ziemlich grundlegend und ich brauchte zwei Wochen, um es zu beheben. Es ist ziemlich technisch, daher erkläre ich die wichtigen technischen Details weiter unten. Aber zuerst müssen Sie wissen, dass der Mehrspielermodus seit der Veröffentlichung der Version 2, die am 0.17.54. Juni veröffentlicht wurde, angesichts vorübergehender Verbindungsprobleme stabiler geworden ist und das Ausblenden von Verzögerungen viel weniger fehlerhaft ist (weniger Bremsen und Teleportieren). Außerdem habe ich die Art und Weise geändert, wie Kampfverzögerungen ausgeblendet werden, und hoffe, dass sie dadurch etwas flüssiger werden.

Multiplayer Mega Pack – Technische Details

Einfach ausgedrückt funktioniert der Mehrspielermodus in einem Spiel folgendermaßen: Alle Clients simulieren den Status des Spiels, indem sie nur Spielereingaben (sogenannte „Eingabeaktionen“) empfangen und senden. Eingabeaktionen). Die Hauptaufgabe des Servers ist die Übertragung Eingabeaktionen und sicherstellen, dass alle Clients die gleichen Aktionen im gleichen Zyklus ausführen. Mehr dazu könnt ihr im Beitrag lesen. FFF-149.

Da der Server entscheiden muss, welche Aktionen er ausführen soll, folgen die Aktionen des Spielers dem folgenden Pfad: Spieleraktion -> Spiel-Client -> Netzwerk -> Server -> Netzwerk -> Spiel-Client. Dies bedeutet, dass jede Aktion des Spielers erst ausgeführt wird, nachdem er einen Hin- und Rückweg durch das Netzwerk zurückgelegt hat. Aus diesem Grund wirkte das Spiel furchtbar langsam, weshalb fast unmittelbar nach dem Erscheinen des Mehrspielermodus im Spiel ein Mechanismus zum Ausblenden von Verzögerungen eingeführt wurde. Latency Hiding simuliert Spielereingaben, ohne die Aktionen anderer Spieler und die Entscheidungsfindung des Servers zu berücksichtigen.

Megapack: Wie Factorio das 200-Spieler-Multiplayer-Problem löste
Factorio hat einen Spielstatus Spielzustand ist der vollständige Zustand der Karte, des Spielers, der Entitäten und allem anderen. Es wird in allen Clients deterministisch simuliert, basierend auf den vom Server empfangenen Aktionen. Der Spielstatus ist heilig, und wenn er sich jemals vom Server oder einem anderen Client unterscheidet, kommt es zu einer Desynchronisierung.

außer Spielzustand Wir haben einen Zustand der Verzögerungen Latenzstatus. Es enthält eine kleine Teilmenge des Hauptzustands. Latenzstatus ist nicht heilig und stellt lediglich ein Bild davon dar, wie der Stand des Spiels in der Zukunft aussehen wird, basierend auf den Eingaben des Spielers Eingabeaktionen.

Zu diesem Zweck bewahren wir eine Kopie der generierten Daten auf Eingabeaktionen in der Verzögerungswarteschlange.

Megapack: Wie Factorio das 200-Spieler-Multiplayer-Problem löste
Das heißt, am Ende des Prozesses auf der Client-Seite sieht das Bild in etwa so aus:

  1. Sich bewerben Eingabeaktionen alle Spieler dazu Spielzustand die Art und Weise, wie diese Eingabeaktionen vom Server empfangen wurden.
  2. Entfernen Sie alles aus der Verzögerungswarteschlange Eingabeaktionen, die laut Server bereits angewendet wurden Spielzustand.
  3. Entfernen Latenzstatus und setzen Sie es zurück, damit es genauso aussieht wie Spielzustand.
  4. Wenden Sie alle Aktionen aus der Verzögerungswarteschlange an Latenzstatus.
  5. Basierend auf Daten Spielzustand и Latenzstatus Rendern Sie das Spiel für den Spieler.

All dies wiederholt sich in jedem Takt.

Zu schwer? Entspannen Sie sich nicht, das ist noch nicht alles. Um unzuverlässige Internetverbindungen auszugleichen, haben wir zwei Mechanismen geschaffen:

  • Übersprungene Ticks: wenn der Server das entscheidet Eingabeaktionen wird im Takt des Spiels ausgeführt, wenn er es nicht erhalten hat Eingabeaktionen Bei einigen Spielern (z. B. aufgrund einer erhöhten Verzögerung) wird er nicht warten, sondern diesem Kunden mitteilen: „Ich habe Ihre nicht berücksichtigt Eingabeaktionen, ich werde versuchen, sie in der nächsten Leiste hinzuzufügen. Dies geschieht, damit aufgrund von Problemen mit der Verbindung (oder mit dem Computer) eines Spielers die Kartenaktualisierung für alle anderen nicht langsamer wird. Das ist erwähnenswert Eingabeaktionen werden nicht ignoriert, sondern einfach verschoben.
  • Vollständige Roundtrip-Latenz: Der Server versucht zu erraten, wie hoch die Roundtrip-Latenz zwischen Client und Server für jeden Client ist. Alle 5 Sekunden verhandelt es nach Bedarf eine neue Verzögerung mit dem Client (je nachdem, wie sich die Verbindung in der Vergangenheit verhalten hat) und erhöht oder verringert die Roundtrip-Verzögerung entsprechend.

An sich sind diese Mechanismen recht einfach, aber wenn sie zusammen verwendet werden (was häufig bei Verbindungsproblemen der Fall ist), wird die Codelogik schwierig zu verwalten und es treten viele Randfälle auf. Wenn diese Mechanismen ins Spiel kommen, müssen der Server und die Verzögerungswarteschlange außerdem eine Besonderheit korrekt implementieren Eingabeaktion berechtigt StopMovementInTheNextTick. Dadurch kann der Charakter bei Verbindungsproblemen nicht alleine laufen (z. B. unter einem Zug).

Jetzt muss ich Ihnen erklären, wie die Entitätsauswahl funktioniert. Einer der übergebenen Typen Eingabeaktion ist eine Änderung im Auswahlstatus einer Entität. Es zeigt jedem an, über welches Wesen der Spieler mit der Maus geschwebt hat. Wie Sie sehen, ist dies eine der am häufigsten von Clients gesendeten Eingabeaktionen. Um Bandbreite zu sparen, haben wir sie so optimiert, dass sie so wenig Platz wie möglich einnimmt. Dies wird wie folgt umgesetzt: Bei der Auswahl jedes Objekts speichert das Spiel nicht die absoluten, hochpräzisen Kartenkoordinaten, sondern einen relativen Offset mit niedriger Genauigkeit von der vorherigen Auswahl. Dies funktioniert gut, da die Mausauswahl normalerweise sehr nahe an der vorherigen Auswahl erfolgt. Daraus ergeben sich zwei wichtige Anforderungen: Eingabeaktionen sollten niemals übersprungen werden und müssen in der richtigen Reihenfolge durchgeführt werden. Diese Anforderungen sind erfüllt Spielzustand. Aber da die Aufgabe Latenzzustand Wenn sie für den Spieler „gut genug aussehen“, sind sie mit dem Verzögerungszustand nicht zufrieden. Latenzstatus berücksichtigt nicht viele GrenzfälleDies ist mit dem Überspringen von Uhren und sich ändernden Verzögerungen bei der Hin- und Rückübertragung verbunden.

Sie können bereits erahnen, wohin das führt. Endlich beginnen wir, die Ursachen des Megapaket-Problems zu erkennen. Die Wurzel des Problems liegt darin, dass die Entitätsauswahllogik darauf basiert Latenzstatus, und dieser Zustand enthält nicht immer die richtigen Informationen. Das Megapaket wird also wie folgt generiert:

  1. Der Player hat Verbindungsprobleme.
  2. Die Mechanismen zum Überspringen von Zyklen und zur Regulierung der Verzögerung der Hin- und Rückübertragung kommen ins Spiel.
  3. Die Verzögerungsstatuswarteschlange berücksichtigt diese Mechanismen nicht. Dies führt dazu, dass einige Aktionen vorzeitig entfernt werden oder in der falschen Reihenfolge ausgeführt werden, was zu einer falschen Ausführung führt Latenzstatus.
  4. Der Player hat keine Verbindungsprobleme und simuliert bis zu 400 Zyklen, um mit dem Server Schritt zu halten.
  5. In jedem Zyklus wird eine neue Aktion generiert und zum Senden an den Server vorbereitet, wodurch sich die Entitätsauswahl ändert.
  6. Der Client sendet ein Megapaket mit über 400 Entitätsauswahländerungen an den Server (und bei anderen Aktionen: Auslösezustand, Gehzustand usw. trat dieses Problem ebenfalls auf).
  7. Der Server empfängt 400 Eingabeaktionen. Da keine einzelne Eingabeaktion übersprungen werden darf, weist es alle Clients an, diese Aktionen auszuführen, und sendet sie über das Netzwerk.

Die Ironie besteht darin, dass der Mechanismus zur Einsparung von Bandbreite zu riesigen Netzwerkpaketen führte.

Wir haben dieses Problem gelöst, indem wir alle Update-Edge-Fälle und die Unterstützung für Verzögerungswarteschlangen behoben haben. Obwohl es ziemlich lange gedauert hat, hat es sich am Ende gelohnt, es richtig zu machen, anstatt sich auf schnelle Hacks zu verlassen.

Source: habr.com

Kommentar hinzufügen