Wie kann ich Daten minimieren, die in einem modernen FPS über ein Netzwerk gesendet werden?

7

Ich bin mir der Snapshot-Interpolation mit der Verwendung der Delta-Komprimierung als einer Technik bewusst, mit der die in einem modernen FPS-Spiel wie Quake 3 gesendete Datenmenge minimiert wird. Aber welche anderen Techniken gibt es?

Neugierde
quelle
1
Dies ist eine äußerst vage Frage. Wenn Sie mehr Details darüber angeben, welche Daten Sie senden müssen und warum Sie der Meinung sind, dass sie noch nicht optimiert sind, erhalten Sie bessere Antworten (oder beantworten Ihre Frage möglicherweise für Sie). Diese Frage ist jedoch unverändert ist zu offen. Wie Sie Daten minimieren können, hängt davon ab, auf welchen Daten Ihr Spiel basiert. Dies hängt vollständig davon ab, wie Sie es entwerfen.
Michael Hoffmann
Es hört sich so an, als müssten Sie einige Hintergrundrecherchen durchführen, um spezifischere Fragen stellen zu können. Wie derzeit geschrieben, werden wahrscheinlich nur Listen mit Techniken erstellt, und diese Arten von Fragen werden in der Regel als nicht zum Thema gehörend geschlossen, da es keine Möglichkeit gibt, eine richtige Antwort auszuwählen. Ich würde vorschlagen, mit Jonathan Blows Inner Product-Artikeln zum Thema Netzwerk zu beginnen, die hier archiviert sind und von den Grundlagen bis zu einigen ziemlich fortgeschrittenen Techniken reichen.
DMGregory

Antworten:

6

Bei der Implementierung unserer Netzwerk-Engine haben wir eine Reihe von Komprimierungstechniken genutzt:

  1. Zuerst schreiben wir alle unsere Schnappschüsse bitweise: Bools sind nur 1 Bit anstelle von 1 Byte (oder mehr, je nach Compiler). Wir haben eine Bitstream-Klasse geschrieben, die Daten liest und in einen Stream schreibt. Dies spart einiges an Daten allein beim Packen von Flags. Ein Beispiel für eine anständige C ++ - BitStream-Klasse finden Sie in der RakNet-Quelle, die Occulus kürzlich zur Verfügung gestellt hat: https://github.com/OculusVR/RakNet
  2. Wir haben die kleinste Möglichkeit gefunden, Daten bitweise darzustellen. Wenn eine Ganzzahl beispielsweise nur im Bereich von 0 bis 15 liegen kann, speichern wir sie im Snapshot nur als 4 Bit. Wir führen dieses Bereichspaket für vorzeichenbehaftete und vorzeichenlose Ganzzahlen durch, um die Datenmenge zu minimieren, die auf Kosten des bitweisen Schreibens der Daten in unseren Snapshot-Stream gesendet wird. Hier fallen CPU-Kosten an, die Datenbandbreite ist jedoch stark reduziert. Wir tun dies auch für Aufzählungen - wenn es nur zwei Zustände gibt, dauert es zum Beispiel nur ein Bit. Wir nutzen hier Vorlagen, um das Schreiben in Code zu vereinfachen.
  3. Wir legen einige Datentypen fest, die quantisiert werden können - Daten, bei denen wir zufrieden sind, dass sie eine gewisse Dezimalgenauigkeit verlieren, um die Bandbreite über das Kabel zu verringern. In Kombination mit der Bereichspackung können wir Gleitkommazahlen von 32 Bit auf eine kleinere, bereichs- und präzisionsspezifische Ebene komprimieren. Auch hier nutzen wir Vorlagen, um das Schreiben in Code zu vereinfachen.
  4. Delta-Komprimierung - Sie haben dies bereits erkannt, aber es hat erhebliche Auswirkungen.
  5. Wir gruppieren Datenblöcke, bei denen die Delta-Komprimierung es uns ermöglicht, eine Reihe verwandter, unveränderlicher Felder unter einem einzigen Dirty-Bit zu gruppieren, um anzuzeigen, ob sie sich geändert haben oder nicht. Dies reduziert die Kosten für das Senden eines Bits für jedes Feld, das angibt, dass es sich NICHT geändert hat. Hier gibt es weniger Gewinn, und man muss vorsichtig sein, wie man sie gruppiert, aber selten wechselnde Felder, die sich im Allgemeinen im Tandem ändern, sind gute Kandidaten.
  6. Wir nehmen das gesamte Paket und komprimieren es mit einer schnellen Komprimierungs-Engine - zum Beispiel lz4. Dies reduziert die Daten noch mehr - alles hilft.
  7. Wir senden KEINE Daten für Objekte, die zu weit entfernt sind, um Teil der Simulation des lokalen Spielers zu sein, und synchronisieren diese Objekte massenweise, wenn der Spieler in die Nähe kommt. Einige Objekte wie Missionsobjekte, Schlüssel und Schlösser sind von diesem System ausgeschlossen.
  8. Wir senden keine Daten, die zuverlässig auf dem Client reproduziert werden können. Zum Beispiel senden wir Animationsstatus und -zeit anstelle der Position jedes Knochens - der Client kann den Charakter zuverlässig mit diesen Informationen darstellen, wodurch wir die Bandbreite sparen, die für das Senden der Transformation jedes Knochens (und aller mit diesen Knochen verbundenen Trefferfelder) anfällt. Effekte usw.). Wir erweitern dies so weit wie möglich. In einem Kommentar wurde darauf hingewiesen, dass "die beste Komprimierung darin besteht, sie überhaupt nicht zu senden".

Ich bin mir sicher, dass es noch andere gibt, aber diese Ideen sollten helfen.

Steven
quelle
1
Das große Problem, das ich hinzufügen möchte, ist, dass Sie nur Daten senden sollten, die der Client nicht zuverlässig selbst reproduzieren kann. Senden Sie also nur die nicht ableitbaren Statusänderungen. Das Komprimieren von Daten, die Sie nicht senden müssen, ist immer noch viel schlimmer, als sie überhaupt nicht zu senden. :)
Sean Middleditch
@ SeanMiddleditch Guter Punkt - ich werde das der Antwort hinzufügen
Steven