Architektur von Zero-Waste-Servern: Analyse des Fortnite Server Optimization Hibernation Proposals
Jeder Multiplayer-Entwickler stößt irgendwann an dieselbe finanzielle Wand: Die Server-Infrastruktur verbrennt Geld, um leeren Raum zu simulieren. Wenn Sie einen Dedicated Server für ein groß angelegtes Battle Royale, Survival-Game oder MMO hochfahren, sind die CPU-Zyklen stark auf Idle-Berechnungen ausgerichtet. Sie zahlen Premium-Cloud-Computing-Raten, um die Schwerkraft für Steine zu berechnen, die niemand ansieht, die KI-Navigation für Gegner ohne Ziele zu verarbeiten und World States in Sektoren aufrechtzuerhalten, in denen keinerlei Spieleraktivität stattfindet.
Kürzlich tauchte in der Unreal Engine-Community ein faszinierender technischer Vorschlag auf, der an die Führung von Epic Games gerichtet war. Die Kern-Thesis? Die massive Skalierung von Fortnite erfordert einen Übergang von einem zentralisierten, wartungsintensiven Hosting-Modell zu einem „Zero-Waste Infrastructure“-Modell. Der Autor argumentierte, dass Epic durch die Eliminierung von Simulationsabfällen die Operating Expenses (Opex) um 60-70 % senken könnte, was es ihnen theoretisch ermöglichen würde, den Preis der Premium-Währung auf eine UVP von 1,99 $ für 1.000 V-Bucks zu senken.
Während die wirtschaftliche Machbarkeit der V-Buck-Preise eine Debatte für Monetization-Designer ist, ist die technische Säule dieses Vorschlags – Sector Physics Hibernation (SGH) – eine Meisterklasse in moderner Server-Architektur.
In dieser Branchenanalyse werden wir die Mechanik des Fortnite Server Optimization Hibernation Proposals zerlegen, untersuchen, wie Logic-Side Culling in Unreal Engine 5 funktioniert, und demonstrieren, wie Sie eine Zero-Waste-Infrastruktur in Ihren eigenen Multiplayer-Titeln implementieren können.
Die Mathematik des Simulationsabfalls
Um zu verstehen, warum Sector Physics Hibernation notwendig ist, müssen wir uns die brutale Mathematik von Dedicated Game Servern ansehen.
Nehmen wir eine Standard-Battle-Royale-Map von 100 km². Zu Beginn eines Matches springen 100 Spieler an verschiedenen Points of Interest ab. Innerhalb der ersten 5 Minuten sind 50 % der Spieler eliminiert, und die überlebenden Spieler konvergieren in Richtung einer schrumpfenden Safe Zone.
Bis Minute 10 enthalten über 70 % der Gesamtfläche der Map null aktive Spieler. Dennoch tickt der Dedicated Server in einem standardmäßigen Authoritative Server-Setup weiterhin den gesamten World State mit 30 Hz.
- Physics Calculations: Rigid Bodies, destruktive Umgebungen und Ballistik werden weiterhin im Speicher verfolgt.
- Actor Ticking: Tausende von
AActor-Instanzen rufen ihreTick()-Funktionen 30 Mal pro Sekunde auf. - NavMesh Processing: Umherstreifende KI oder dynamische Hindernisse fragen weiterhin das Navigation Mesh ab.
Wenn Sie Ihre Server auf AWS c5.2xlarge-Instanzen betreiben, zahlen Sie etwa 0,34 $ pro Stunde und Maschine. Wenn eine einzelne Maschine nur zwei 100-Spieler-Game-Instanzen hosten kann, weil die CPU mit der Berechnung von leerem Raum ausgelastet ist, ist Ihre Skalierung massiv eingeschränkt.
Der Vorschlag legt nahe, dass Entwickler durch die Rückgewinnung dieses verschwendeten CPU-Overheads entweder 5-6 Game-Instanzen auf derselben Hardware unterbringen können (was die Serverrechnungen um ca. 60 % senkt) oder die zurückgewonnene Rechenleistung nutzen können, um die globale Server-Tickrate von 30 Hz auf 60 Hz+ zu erhöhen, was eine perfekte Hit Registration und ein flüssiges Gameplay gewährleistet.
Deep Dive: Sector Physics Hibernation in UE5
Die vorgeschlagene technische Lösung basiert auf der Nutzung des vorhandenen World Partition-Systems der Unreal Engine 5, wobei der primäre Use Case jedoch vom Client-Side Memory Management auf das Server-Side CPU Management umgestellt wird.
Das Problem mit Standard-Dedicated-Servern
Standardmäßig streamt das World Partition von UE5 Zellen für den Client basierend auf deren Entfernung von der Streaming-Quelle (der Spielerkamera) ein und aus. Dies ist hervorragend geeignet, um die Speichernutzung des Clients niedrig und die Frameraten hoch zu halten.
Der Dedicated Server lädt jedoch normalerweise die gesamte Map in den Speicher, um die Autorität zu wahren. Wenn ein Scharfschütze eine Kugel über ein Tal abfeuert oder ein globales Event ausgelöst wird, benötigt der Server die Kollisionsdaten und Actor-States sofort, um die Aktion zu validieren. Das dynamische Laden und Entladen von Daten von der Festplatte auf dem Server (Level Streaming) ist oft zu langsam und verursacht massive Ruckler, was die Tickrate ruiniert.
Die SGH-Lösung: Logic-Side Culling
Anstatt den Sektor aus dem Speicher zu entladen (was IO-Bottlenecks verursacht), schlägt Sector Physics Hibernation CPU-Sleep States vor.
Der Sektor bleibt im RAM, aber alle Ticks, Physics-Berechnungen und Status-Updates werden aggressiv pausiert. Wenn eine Spatial Grid Cell eines Sektors null aktive Entitäten (Spieler, fahrzeuge im Besitz von Spielern oder aktive Projektile) erkennt, setzt der Server die CPU-Zuweisung für dieses spezifische Grid aus.
Implementierung eines Hibernation Managers in C++
Um dies in der Unreal Engine zu bauen, benötigen Sie ein Subsystem, das Spatial Grid Cells überwacht und den Tick-Status von Actoren darin dynamisch umschaltet. Unten sehen Sie einen vereinfachten Architektur-Prototyp für die Implementierung eines SectorHibernationManager.
#include "SectorHibernationManager.h"
#include "EngineUtils.h"
#include "GameFramework/Actor.h"
#include "GameFramework/PlayerController.h"
void USectorHibernationManager::Initialize(FSubsystemCollectionBase& Collection)
{
Super::Initialize(Collection);
HibernationCheckInterval = 2.0f; // Alle 2 Sekunden prüfen
TimeSinceLastCheck = 0.0f;
GridCellSize = 10000.0f; // 100m Grid-Zellen
}
void USectorHibernationManager::Tick(float DeltaTime)
{
TimeSinceLastCheck += DeltaTime;
if (TimeSinceLastCheck >= HibernationCheckInterval)
{
EvaluateSectors();
TimeSinceLastCheck = 0.0f;
}
}
void USectorHibernationManager::EvaluateSectors()
{
UWorld* World = GetWorld();
if (!World) return;
// Schritt 1: Aktive Spielerpositionen auf Grid-Zellen mappen
TSet<FIntVector> ActiveCells;
for (FConstPlayerControllerIterator Iterator = World->GetPlayerControllerIterator(); Iterator; ++Iterator)
{
APlayerController* PC = Iterator->Get();
if (PC && PC->GetPawn())
{
FVector PlayerPos = PC->GetPawn()->GetActorLocation();
FIntVector CellCoord = FIntVector(
FMath::FloorToInt(PlayerPos.X / GridCellSize),
FMath::FloorToInt(PlayerPos.Y / GridCellSize),
FMath::FloorToInt(PlayerPos.Z / GridCellSize)
);
// Diese Zelle und benachbarte Zellen als aktiv markieren (Buffer Zone)
MarkAdjacentCellsActive(CellCoord, ActiveCells);
}
}
// Schritt 2: Hibernatable Actors durchlaufen und Tick umschalten
for (TActorIterator<AActor> ActorItr(World); ActorItr; ++ActorItr)
{
AActor* Actor = *ActorItr;
// Essenzielle Infrastruktur-Actors überspringen
if (!Actor->ActorHasTag(FName("Hibernatable"))) continue;
FVector ActorPos = Actor->GetActorLocation();
FIntVector ActorCell = FIntVector(
FMath::FloorToInt(ActorPos.X / GridCellSize),
FMath::FloorToInt(ActorPos.Y / GridCellSize),
FMath::FloorToInt(ActorPos.Z / GridCellSize)
);
bool bShouldBeActive = ActiveCells.Contains(ActorCell);
if (bShouldBeActive && !Actor->IsActorTickEnabled())
{
// Aufwachen
Actor->SetActorTickEnabled(true);
Actor->SetActorEnableCollision(true);
}
else if (!bShouldBeActive && Actor->IsActorTickEnabled())
{
// Schlafen gehen
Actor->SetActorTickEnabled(false);
// Optional: Kollision auf einfache Abfragen reduzieren, um Physics-Thread-Zeit zu sparen
Actor->SetActorEnableCollision(false);
}
}
}
Die Komplexität der „Wake-Up“-Phase
Der obige Code veranschaulicht das Kernkonzept, aber die eigentliche technische Herausforderung liegt in der Wake-Up-Phase. Wenn ein Spieler ein Hochgeschwindigkeits-Scharfschützengewehr in einen schlafenden Sektor abfeuert, wird das Projektil die Grenze überschreiten, bevor der 2-Sekunden-Evaluierungs-Loop es erfasst.
Wenn der Sektor erst aufwacht, nachdem die Kugel angekommen ist, kommt es zu einem katastrophalen Desync. Die Kugel könnte direkt durch ein hibernierendes Fahrzeug fliegen, weil dessen Kollision deaktiviert war. Dieses Phänomen ist eng verwandt mit den Problemen, die in unserem Guide The Unreal Engine Multiplayer Sync Bug Ruining Your World States And How To Fix It beschrieben werden, wo Zeitdiskrepanzen zwischen Server-State und Client-Prediction die Simulation komplett zerstören.
Um dies zu lösen, erfordert eine Zero-Waste-Infrastruktur Predictive Wake-Ups. Anstatt nur Spielerpositionen zu verfolgen, muss der Server die Vorwärtsgeschwindigkeitsvektoren aller aktiven Projektile und Hochgeschwindigkeitsfahrzeuge berechnen. Wenn ein Vektor eine schlafende Grid-Zelle schneidet, muss der Server sofort ein Wake-Up-Event für diese spezifische Zelle erzwingen, noch bevor das Objekt eintrifft.
Orchestrierung von Zero-Waste-Servern im großen Stil
Die Implementierung von Logic-Side Culling in Ihrer Game Engine ist nur die halbe Miete. Die andere Hälfte ist die Infrastruktur-Orchestrierung.
Wenn Ihr UE5 Dedicated Server seinen CPU-Footprint dynamisch erfolgreich um 60 % reduziert, muss Ihre Server-Hosting-Umgebung intelligent genug sein, um diesen Rückgang des Ressourcenverbrauchs zu erkennen und neue Game-Instanzen auf denselben Hardware-Node zu packen.
Diese Orchestrierung selbst zu bauen, erfordert einen immensen Aufwand an DevOps-Engineering. Sie müssten Kubernetes-Cluster bereitstellen, Agones für das Game Server Lifecycle Management konfigurieren, benutzerdefinierte Scaling-Metriken basierend auf der CPU-Auslastung schreiben und Load Balancer verwalten, um Spieler zu den richtigen Instanzen zu leiten. Das sind locker 4-6 Monate dedizierte Infrastrukturarbeit – Zeit, die direkt von der eigentlichen Entwicklung Ihres Spiels abgezogen wird.
Mit horizOn sind diese Backend-Orchestrierungsdienste bereits vorkonfiguriert. Die Plattform übernimmt das dynamische Instance Packing, Auto-Scaling basierend auf der Serverlast in Echtzeit und automatisierte Deployment-Pipelines für Ihre Dedicated Server Builds. Indem Sie ein spezialisiertes Backend-as-a-Service die Infrastruktur verwalten lassen, können Sie Ihr Multiplayer-Spiel veröffentlichen, anstatt ein halbes Jahr mit Kubernetes-Manifesten zu kämpfen.
Darüber hinaus erhöhen Sie das Risiko von Noisy-Neighbor-Problemen, die Ihren Network-Thread beeinträchtigen, wenn Sie mehr Instanzen auf einen einzelnen Node packen. Die Absicherung Ihres Netcodes gegen diese Bottlenecks ist entscheidend – ein Thema, das wir ausführlich in The Uefn Server Performance Exploit Explained Hard Armoring Your Unreal Engine Netcode behandeln.
Best Practices für Zero-Waste Multiplayer-Architektur
Egal, ob Sie ein 100-Spieler Battle Royale oder ein persistentes Open-World Survival-Game bauen, die Implementierung von Hibernation und Zero-Waste-Techniken erfordert strikte architektonische Disziplin. Hier sind fünf praxiserprobte Best Practices, um sicherzustellen, dass Ihre Server-Opex niedrig bleibt, ohne das Spielerlebnis zu opfern:
1. Game State vom Tick-Loop entkoppeln
Der größte Feind der Server-Performance ist das kontinuierliche Polling von Daten. Verwenden Sie niemals Tick(), um zu prüfen, ob ein Event eintreten sollte. Wechseln Sie vollständig zu einer Event-Driven Architecture. Wenn ein Lagerfeuer nach 5 Minuten ausbrennen soll, lassen Sie es nicht jeden Frame ticken, um die Zeit zu subtrahieren. Setzen Sie einen Timer-Delegate, der genau einmal nach 300 Sekunden feuert. Dies ermöglicht es dem Lagerfeuer-Actor, 4 Minuten und 59 Sekunden lang komplett zu schlafen.
2. Aggressives NetCullDistanceSquared implementieren
Unreal Engine bestimmt basierend auf NetCullDistanceSquared, welche Actoren an welche Clients repliziert werden. Viele Entwickler belassen dies bei den Standardwerten, was den Server zwingt, Daten für Actoren zu serialisieren und zu komprimieren, die hunderte Meter von einem Spieler entfernt sind. Überprüfen Sie Ihre Cull-Distanzen. Eine fallengelassene Waffe muss nicht über 5.000 Einheiten (50 Meter) hinaus repliziert werden. Berechnen Sie den absolut minimalen Radius, der für Ihren Gameplay-Loop erforderlich ist, und setzen Sie diesen strikt durch.
3. Spatial Hash Grids für O(1)-Lookups verwenden
Bei der Berechnung, welche Actoren schlafen gehen sollen, wird das Iterieren über jeden Actor in der Welt (TActorIterator) selbst zum Bottleneck, wenn Sie 100.000 Entitäten haben. Implementieren Sie ein Spatial Hash Grid. Wenn sich ein Actor bewegt, aktualisiert er seine Position in der Hash Map. Dies ermöglicht es Ihrem Hibernation Manager, „Was befindet sich in Grid-Zelle X?“ in O(1)-Zeitkomplexität abzufragen, wodurch die Hibernation-Evaluierung auf der CPU praktisch kostenlos wird.
4. Buffer Zones für nahtlose Wake-Ups nutzen
Lassen Sie einen Sektor niemals direkt am Rand der Sichtweite eines Spielers hibernieren. Halten Sie immer eine „Buffer Zone“ aus aktiven Sektoren von mindestens einer Grid-Zelle Breite um jede aktive Entität aufrecht. Wenn Ihre Grid-Zellen 100 Meter breit sind und sich ein Spieler in Zelle A befindet, müssen alle benachbarten Zellen (ein 3x3-Grid) voll aktiv bleiben. Dies garantiert, dass die Zielzelle bereits vollständig initialisiert ist und tickt, wenn ein Spieler plötzlich über eine Grenze sprintet.
5. Dedicated Server Builds regelmäßig profilen
Raten Sie nicht, was Ihre CPU frisst. Verwenden Sie Unreal Insights in einer gepackten Dedicated-Server-Umgebung mit simulierter Last. Achten Sie speziell auf die GameThread-Timings. Wenn Sie sehen, dass Physics oder TickTime den Thread-Graphen dominieren, während Spieler stillstehen, versagt Ihre Hibernation-Logik. Telemetrie ist der einzige Weg, um zu validieren, dass Ihre Zero-Waste-Architektur in der Realität funktioniert, nicht nur in der Theorie.
Die Zukunft der Server-Opex
Der Vorschlag der Fortnite-Community wirft ein Licht auf eine kritische Wahrheit: Der aktuelle Branchenstandard, Server-Performance mit teurem Cloud-Computing per Brute-Force zu erzwingen, ist nicht nachhaltig. Da Welten größer und Spielerzahlen höher werden, wird die lineare Skalierung der Infrastrukturkosten die Live-Ops-Budgets langsam austrocknen.
Sector Physics Hibernation, Logic-Side Culling und dynamisches Instance Packing sind nicht mehr nur Optimierungen für AAA-Studios; sie sind Überlebensvoraussetzungen für Multiplayer-Spiele aller Größen. Indem Sie frühzeitig in Ihrem Entwicklungszyklus ein Zero-Waste-Mindset annehmen, stellen Sie sicher, dass die Rentabilität Ihres Spiels parallel zu seiner Spielerbasis skaliert.
Wenn Sie bereit sind, dynamisches Server-Scaling ohne den DevOps-Stress zu implementieren, testen Sie horizOn kostenlos oder werfen Sie einen Blick in die API-Docs, um zu sehen, wie nahtlos Multiplayer-Infrastruktur sein kann.