Terug naar Blog

Architectuur van Zero-Waste Servers: Analyse van het Fortnite Server Optimization Hibernation Voorstel

Gepubliceerd op 25 februari 2026
Architectuur van Zero-Waste Servers: Analyse van het Fortnite Server Optimization Hibernation Voorstel

Elke multiplayer-ontwikkelaar loopt uiteindelijk tegen dezelfde financiële muur aan: je serverinfrastructuur verbrandt geld om lege ruimte te simuleren. Wanneer je een Dedicated Server opstart voor een grootschalige battle royale, survivalgame of MMO, zijn de CPU-cycli zwaar scheefgetrokken richting idle-berekeningen. Je betaalt premium Cloud Computing-tarieven om zwaartekracht te berekenen voor rotsen waar niemand naar kijkt, AI-navigatie te verwerken voor vijanden zonder doelen, en World States te onderhouden in sectoren die volledig verstoken zijn van spelersactiviteit.

Onlangs verscheen er een fascinerend technisch voorstel in de Unreal Engine-community, gericht aan de directie van Epic Games. De kernthese? De enorme schaal van Fortnite vereist een overgang van een gecentraliseerd, onderhoudsintensief hostingmodel naar een "Zero-Waste Infrastructure"-model. De auteur betoogde dat Epic door het elimineren van simulatieverspilling de Operating Expenses (Opex) met 60-70% zou kunnen verlagen, waardoor ze theoretisch de prijs van premium valuta zouden kunnen verlagen naar een MSRP van $1,99 voor 1.000 V-Bucks.

Hoewel de economische haalbaarheid van de V-Buck-prijzen een debat is voor monetization designers, is de technische pijler van dit voorstel — Sector Physics Hibernation (SGH) — een masterclass in moderne serverarchitectuur.

In deze industrie-analyse gaan we de mechanica van het Fortnite server optimization hibernation voorstel ontleden, onderzoeken we hoe Logic-Side Culling werkt in Unreal Engine 5, en laten we zien hoe je een zero-waste infrastructuur kunt implementeren in je eigen multiplayer-titels.

De Wiskunde van Simulatieverspilling

Om te begrijpen waarom Sector Physics Hibernation noodzakelijk is, moeten we kijken naar de brute wiskunde van Dedicated Servers.

Neem een standaard battle royale-map van 100 km². Aan het begin van een match droppen 100 spelers op verschillende Points of Interest. Binnen de eerste 5 minuten is 50% van de spelers geëlimineerd en de overlevende spelers convergeren naar een krimpende Safe Zone.

Tegen minuut 10 bevat meer dan 70% van de totale oppervlakte van de map nul actieve spelers. Toch blijft de Dedicated Server in een standaard Authoritative Server-setup de volledige World State op 30Hz sychroniseren.

  • Physics Calculations: Rigid Bodies, vernietigbare omgevingen en ballistiek worden nog steeds in het geheugen bijgehouden.
  • Actor Ticking: Duizenden AActor-instanties roepen hun Tick()-functies 30 keer per seconde aan.
  • NavMesh Processing: Rondzwervende AI of dynamische obstakels blijven de Navigation Mesh bevragen.

Als je je servers draait op AWS c5.2xlarge instanties, betaal je ongeveer $0,34 per uur per machine. Als een enkele machine slechts twee game-instanties van 100 spelers kan hosten omdat de CPU maximaal belast wordt door het berekenen van lege ruimte, is je schaalbaarheid ernstig beperkt.

Het voorstel suggereert dat door deze verspilde CPU-overhead terug te winnen, ontwikkelaars ofwel 5-6 game-instanties op dezelfde hardware kunnen plaatsen (waardoor de serverrekeningen met ~60% dalen), of die teruggewonnen rekenkracht kunnen gebruiken om de globale server Tick Rate te verhogen van 30Hz naar 60Hz+, wat zorgt voor perfecte Hit Registration en vloeiende gameplay.

Deep Dive: Sector Physics Hibernation in UE5

De voorgestelde technische oplossing vertrouwt op het gebruik van het bestaande World Partition-systeem van Unreal Engine 5, maar verlegt de primaire use case van geheugenbeheer aan de clientzijde naar CPU-beheer aan de serverzijde.

Het Probleem met Standaard Dedicated Servers

Standaard streamt de World Partition van UE5 cellen in en uit voor de client op basis van hun afstand tot de streamingbron (de camera van de speler). Dit is uitstekend om het geheugengebruik van de client laag en de framerates hoog te houden.

De Dedicated Server laadt echter meestal de hele map in het geheugen om de autoriteit te behouden. Als een sluipschutter een kogel door een vallei schiet, of als een globaal evenement wordt geactiveerd, heeft de server de botsingsgegevens en Actor States direct beschikbaar nodig om de actie te valideren. Gegevens dynamisch laden en lossen van schijf op de server (Level Streaming) is vaak te traag en veroorzaakt enorme haperingen, wat de Tick Rate ruïneert.

De SGH-oplossing: Logic-Side Culling

In plaats van de sector uit het geheugen te lossen (wat IO-bottlenecks veroorzaakt), stelt Sector Physics Hibernation CPU-Sleep States voor.

De sector blijft in het RAM, maar alle Ticks, physics-berekeningen en statusupdates worden agressief gepauzeerd. Wanneer een Spatial Grid-cel van een sector nul actieve entiteiten detecteert (spelers, voertuigen van spelers of actieve projectielen), schort de server de CPU-toewijzing voor dat specifieke grid op.

Een Hibernation Manager Implementeren in C++

Om dit in Unreal Engine te bouwen, heb je een subsysteem nodig dat Spatial Grid-cellen bewaakt en dynamisch de Tick-status van actors daarin omschakelt. Hieronder staat een vereenvoudigd architecturaal prototype van hoe je een SectorHibernationManager kunt implementeren.

#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; // Elke 2 seconden controleren
    TimeSinceLastCheck = 0.0f;
    GridCellSize = 10000.0f; // 100m grid-cellen
}

void USectorHibernationManager::Tick(float DeltaTime)
{
    TimeSinceLastCheck += DeltaTime;
    if (TimeSinceLastCheck >= HibernationCheckInterval)
    { 
        EvaluateSectors();
        TimeSinceLastCheck = 0.0f;
    }
}

void USectorHibernationManager::EvaluateSectors()
{
    UWorld* World = GetWorld();
    if (!World) return;

    // Stap 1: Actieve spelerposities mappen naar grid-cellen
    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)
            );
            
            // Markeer deze cel en aangrenzende cellen als actief (bufferzone)
            MarkAdjacentCellsActive(CellCoord, ActiveCells);
        }
    }

    // Stap 2: Loop door hibernatable actors en schakel tick om
    for (TActorIterator<AActor> ActorItr(World); ActorItr; ++ActorItr)
    { 
        AActor* Actor = *ActorItr;
        
        // Sla essentiële infrastructuur-actors over
        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())
        { 
            // Wakker worden
            Actor->SetActorTickEnabled(true);
            Actor->SetActorEnableCollision(true);
        }
        else if (!bShouldBeActive && Actor->IsActorTickEnabled())
        { 
            // Gaan slapen
            Actor->SetActorTickEnabled(false);
            // Optioneel: Verlaag botsing naar alleen eenvoudige queries om physics-thread tijd te besparen
            Actor->SetActorEnableCollision(false); 
        }
    }
}

De Complexiteit van de "Wake-Up" Fase

De bovenstaande code illustreert het kernconcept, maar de echte technische uitdaging ligt in de wake-up fase. Als een speler een sluipschuttersgeweer met hoge snelheid in een slapende sector afvuurt, zal het projectiel de grens overschrijden voordat de evaluatielus van 2 seconden het opmerkt.

Als de sector wakker wordt nadat de kogel is aangekomen, ervaar je een catastrofale desync. De kogel zou dwars door een hibernerend voertuig kunnen gaan omdat de botsing was uitgeschakeld. Dit fenomeen is nauw verwant aan de problemen die worden beschreven in onze gids over The Unreal Engine Multiplayer Sync Bug Ruining Your World States And How To Fix It, waar tijdsverschillen tussen de serverstatus en de clientvoorspelling de simulatie volledig verbreken.

Om dit op te lossen, vereist een zero-waste infrastructuur Predictive Wake-Ups. In plaats van alleen spelerposities te volgen, moet de server de voorwaartse snelheidsvectoren van alle actieve projectielen en hogesnelheidsvoertuigen berekenen. Als een vector een slapende grid-cel snijdt, moet de server onmiddellijk een wake-up event forceren op die specifieke cel vóór de aankomst van het object.

Zero-Waste Servers Orchestreren op Schaal

Het implementeren van Logic-Side Culling in je game engine is slechts de helft van de strijd. De andere helft is infrastructuur-orchestratie.

Als je UE5 Dedicated Server zijn CPU-voetafdruk met succes dynamisch met 60% vermindert, moet je serverhostingomgeving slim genoeg zijn om die daling in resourcegebruik te herkennen en nieuwe game-instanties op hetzelfde hardwareknooppunt te plaatsen.

Dit zelf bouwen vereist een enorme hoeveelheid DevOps-engineering. Je zou Kubernetes-clusters moeten implementeren, Agones moeten configureren voor het beheer van de levenscyclus van gameservers, aangepaste schalingsstatistieken moeten schrijven op basis van CPU-gebruik en load balancers moeten beheren om spelers naar de juiste instanties te leiden. Dit is gemakkelijk 4-6 maanden toegewijd infrastructuurwerk — tijd die direct ten koste gaat van het bouwen van je game.

Met horizOn zijn deze backend-orchestratiediensten vooraf geconfigureerd. Het platform regelt dynamische instance packing, auto-scaling op basis van real-time serverbelasting en geautomatiseerde deployment pipelines voor je Dedicated Server-builds. Door een gespecialiseerde Backend-as-a-Service de infrastructuur te laten afhandelen, kun je je multiplayer-game releasen in plaats van een half jaar te vechten met Kubernetes-manifesten.

Bovendien, wanneer je meer instanties op een enkel knooppunt plaatst, verhoog je het risico op Noisy Neighbor-problemen die je netwerkthread beïnvloeden. Het beveiligen van je Netcode tegen deze bottlenecks is cruciaal, een onderwerp dat we uitgebreid behandelen in The Uefn Server Performance Exploit Explained Hard Armoring Your Unreal Engine Netcode.

Best Practices voor Zero-Waste Multiplayer Architectuur

Of je nu een battle royale voor 100 spelers bouwt of een persistente open-world survivalgame, het implementeren van hibernation en zero-waste technieken vereist strikte architecturale discipline. Hier zijn vijf beproefde best practices om ervoor te zorgen dat je server-Opex laag blijft zonder de spelervaring op te offeren:

1. Ontkoppel de Game State van de Tick Loop

De grootste vijand van serverprestaties is het continu pollen van gegevens. Gebruik nooit Tick() om te controleren of een gebeurtenis moet plaatsvinden. Stap volledig over op een Event-Driven Architecture. Als een kampvuur na 5 minuten moet uitbranden, laat het dan niet elke frame ticken om tijd af te trekken. Stel een timer-delegate in die precies één keer na 300 seconden afgaat. Hierdoor kan de kampvuur-actor 4 minuten en 59 seconden lang volledig slapen.

2. Implementeer Agressieve NetCullDistanceSquared

Unreal Engine bepaalt welke actors naar welke clients moeten worden gerepliceerd op basis van NetCullDistanceSquared. Veel ontwikkelaars laten dit op de standaardwaarden staan, waardoor de server gedwongen wordt om gegevens te serialiseren en te comprimeren voor actors die honderden meters van een speler verwijderd zijn. Controleer je cull-afstanden. Een gedropt wapen hoeft niet verder dan 5.000 eenheden (50 meter) te worden gerepliceerd. Bereken de absolute minimumradius die nodig is voor je Gameplay Loop en handhaaf deze strikt.

3. Gebruik Spatial Hash Grids voor O(1) Lookups

Bij het berekenen welke actors moeten gaan slapen, wordt het itereren over elke actor in de wereld (TActorIterator) op zichzelf een bottleneck als je 100.000 entiteiten hebt. Implementeer een Spatial Hash Grid. Wanneer een actor beweegt, werkt deze zijn positie bij in de hash-map. Hierdoor kan je Hibernation Manager in O(1) tijdcomplexiteit opvragen "Wat bevindt zich in Grid-cel X?", waardoor de hibernation-evaluatie vrijwel gratis is voor de CPU.

4. Gebruik Bufferzones voor Naadloze Wake-Ups

Hiberneer een sector nooit precies tot aan de rand van het zicht van een speler. Houd altijd een "Bufferzone" van actieve sectoren aan van ten minste één grid-cel breed rond elke actieve entiteit. Als je grid-cellen 100 meter breed zijn en een speler bevindt zich in Cel A, dan moeten alle aangrenzende cellen (een 3x3 grid) volledig actief blijven. Dit garandeert dat als een speler plotseling over een grens sprint, de doelcel al volledig geïnitialiseerd is en tickt.

5. Profileer je Dedicated Server-builds regelmatig

Raad niet wat je CPU opeet. Gebruik Unreal Insights in een gepackagede Dedicated Server-omgeving met gesimuleerde belasting. Kijk specifiek naar de GameThread-timings. Als je ziet dat Physics of TickTime de thread-grafiek domineren wanneer spelers stilstaan, faalt je hibernation-logica. Telemetrie is de enige manier om te valideren dat je zero-waste architectuur in de praktijk werkt, niet alleen in theorie.

De Toekomst van Server Opex

Het voorstel van de Fortnite-community werpt een licht op een kritieke waarheid: de huidige industriestandaard van het brute-forcen van serverprestaties met dure Cloud Compute is onhoudbaar. Naarmate werelden groter worden en spelersaantallen toenemen, zal de lineaire schaling van infrastructuurkosten de live-ops budgetten langzaam leegbloeden.

Sector Physics Hibernation, Logic-Side Culling en dynamische instance packing zijn niet langer alleen optimalisaties voor AAA-studio's; het zijn overlevingseisen voor multiplayer-games van alle groottes. Door vroeg in je ontwikkelingscyclus een zero-waste mindset aan te nemen, zorg je ervoor dat de winstgevendheid van je game meeschaalt met je spelersbestand.

Als je klaar bent om dynamische serverschaling te implementeren zonder de DevOps-hoofdpijn, probeer dan horizOn gratis of bekijk de API-docs om te zien hoe naadloos multiplayer-infrastructuur kan zijn.


Bron: [Technical Proposal] Unified Operational Sovereignty: Decoupling Opex to Enable a $1.99 V-Buck Economy