Het oplossen van de Unreal Engine UBA Executor UBT Error in UE 5.8 Source Builds
Kort samengevat
Deze handleiding legt uit hoe je de 'unreal engine uba executor ubt error' in Unreal Engine 5.8 source builds oplost. We analyseren de oorzaak van de crash bij recursieve UBT-aanroepen, zoals bij het compileren van de UnrealHeaderTool. Vervolgens bespreken we drie oplossingen: een globale XML-configuratie, een C#-patch voor de ExecutorFactory om automatisch terug te vallen op de ParallelExecutor, en specifieke command-line flags. Tot slot delen we best practices voor het optimaliseren van engine-compilaties en concurrency.
Weinig dingen vertragen het momentum van een studio zo erg als een gecrashte engine build, vooral wanneer je Unreal Engine 5.8.0 compileert vanaf source en Visual Studio stopt met een cryptische exception. De build faalt met een unhandled exception die direct verwijst naar UBAExecutor.cs. Deze specifieke blocker, bekend als de unreal engine uba executor ubt error, legt de compilatie volledig stil. Het voorkomt dat de build graph de generatie van kritieke helper-programma's zoals UnrealHeaderTool kan voltooien. In deze handleiding leggen we uit waarom Unreal Build Accelerator (UBA) moeite heeft met geneste aanroepen, hoe de standaardconfiguratie faalt, en hoe je de engine source kunt patchen om een werkende build pipeline te herstellen.
De architectuur van het build system begrijpen
Om te begrijpen waarom deze error optreedt, moeten we kijken naar hoe de Unreal Build Tool (UBT) de compilatie orchestreert. Unreal Engine codebases zijn gigantisch en bevatten vaak tienduizenden source-bestanden. Om deze efficiënt te compileren, fungeert UBT als een meta-build system dat dependency graphs genereert en compile-acties distribueert.
Wat is Unreal Build Accelerator?
Epic Games introduceerde de Unreal Build Accelerator (UBA) als de standaard compilation executor om oudere distributiesystemen te vervangen. UBA is ontworpen om compilatie te versnellen door gebruik te maken van een lichtgewicht gevirtualiseerd bestandssysteem (VFS) om I/O-operaties op bestanden te onderscheppen. Het stuurt compilertaken naar meerdere lokale cores of verdeelt ze over Horde build nodes.
Op een standaard build-machine met 64 cores kan UBA de tijd voor een clean engine-compilatie verkorten van ~90 minuten naar minder dan ~25 minuten. Echter, omdat UBA vertrouwt op een gecentraliseerde lokale agent om I/O te onderscheppen, vereist het strikte controle over hoe compilerprocessen worden gestart.
Het mechanisme van recursieve UBT-aanroepen
Tijdens een compilatie-run komt UBT vaak targets tegen die gebouwd moeten worden voordat de primaire engine-binaries kunnen compileren. Voordat bijvoorbeeld de UnrealEditor-executable wordt gecompileerd, moet UBT UnrealHeaderTool (UHT) compileren om header-bestanden te parsen en reflection metadata te genereren.
Om dit te bereiken, start het primaire UBT-proces een genest, secundair UBT-proces om de vereiste target te bouwen. Deze geneste aanroep wordt een recursieve UBT-aanroep genoemd. Wanneer een recursieve UBT-aanroep actief is, stelt UBT een interne vlag in (UnrealBuildTool.IsRecursive = true) en geeft environment variables door om het proces als genest te markeren.
Waarom de UBA Executor crasht bij recursieve aanroepen
De crash treedt op omdat de UBA executor niet is ontworpen om geneste compilatie-loops te ondersteunen. Laten we kijken naar de typische callstack die UBT genereert wanneer deze fout optreedt in Visual Studio:
Unhandled exception: Exception: UBA executor is not expected to be invoked from a recursive UBT call.
at UnrealBuildTool.UBAExecutor.Init(IEnumerable`1 targetDescriptors, ILogger logger) in UnrealEngine\Engine\Source\Programs\UnrealBuildTool\Executors\UnrealBuildAccelerator\UBAExecutor.cs:line 315
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
at UnrealBuildTool.UBAExecutor.ExecuteActionsAsync(IEnumerable`1 inputActions, ILogger logger) in UnrealEngine\Engine\Source\Programs\UnrealBuildTool\Executors\UnrealBuildAccelerator\UBAExecutor.cs:line 617
at UnrealBuildTool.ActionGraph.InternalExecuteActions(ActionExecutor Executor, List`1 ActionsToExecute, ILogger Logger) in UnrealEngine\Engine\Source\Programs\UnrealBuildTool\Actions\ActionGraph.cs:line 435
De safety check in UBAExecutor.cs
Binnen de UBAExecutor.Init-methode (rond regel 315 van UBAExecutor.cs) dwingt de engine expliciet een recursie-safety check af:
// Engine/Source/Programs/UnrealBuildTool/Executors/UnrealBuildAccelerator/UBAExecutor.cs
public void Init(IEnumerable<TargetDescriptor> TargetDescriptors, ILogger Logger)
{
if (UnrealBuildTool.IsRecursive)
{
throw new Exception("UBA executor is not expected to be invoked from a recursive UBT call.");
}
// Virtualized file system and network initialization follow...
}
Deze safety check heeft een belangrijke reden. De lokale UBA-agent bindt zich aan specifieke TCP poorten om te communiceren met gevirtualiseerde compiler-helperprocessen.
Als een recursieve UBT-aanroep zou proberen een tweede instantie van de UBA executor te initialiseren, zouden beide instanties proberen te binden aan dezelfde netwerksockets en met elkaar conflicteren over de gevirtualiseerde bestandssysteem-hooks. Dit zou leiden tot socket-allocatiefouten, bestandssysteemcorruptie of oneindige build deadlocks. De exception fungeert hier als een beschermende barrière.
De root cause: Foutieve executor-selectie
De daadwerkelijke bug in de source builds van Unreal Engine 5.8.0 is niet deze safety check. Het is eerder het falen van de executor factory-logica om correct om te gaan met recursieve aanroepen.
Wanneer UBT bepaalt welke executor moet worden gebruikt, raadpleegt het de ExecutorFactory.cs-klasse. De factory controleert of UBA is ingeschakeld en beschikbaar is op de host-machine.
Het controleert echter niet of het huidige UBT-proces een recursieve uitvoering is. Hierdoor probeert de factory bij het opstarten van het secundaire UBT-proces om UnrealHeaderTool te compileren, de UBAExecutor toe te wijzen aan de geneste build, wat de crash in de Init-methode veroorzaakt.
De XML-configuratievalkuil
Veel developers proberen dit probleem te omzeilen door het globale BuildConfiguration.xml-bestand aan te passen. Het standaardadvies in oudere forumposts is om UBA uit te schakelen door de volgende tag te deactiveren:
<?xml version="1.0" encoding="utf-8" ?>
<Configuration xmlns="https://www.unrealengine.com/BuildConfiguration">
<BuildConfiguration>
<bAllowUBA>false</bAllowUBA>
</BuildConfiguration>
</Configuration>
Waarom bAllowUBA wordt genegeerd in UE 5.8
Als je de bovenstaande XML-configuratie toepast op een Unreal Engine 5.8.0 source build, zal de compiler nog steeds proberen UBA te starten en de exception opwerpen. Dit komt doordat het build-configuratiesysteem van de engine is gerefactord.
De oude bAllowUBA-vlag is deprecated en is niet langer gekoppeld aan de executor-selectielogica. In plaats daarvan wordt het gedrag van UBA beheerd door twee afzonderlijke properties: bAllowUBAExecutor en bAllowUBALocalExecutor.
Omdat UBT bAllowUBAExecutor niet in je XML vindt, valt het terug op de standaardwaarde true. Dit overschrijft geruisloos je poging om UBA uit te schakelen.
Correcte XML-structuur voor UBA-configuratie
Om UBA succesvol uit te schakelen via configuratiebestanden, moet je de bijgewerkte XML-propertynamen gebruiken. Hieronder staat de juiste structuur om UBT te dwingen terug te vallen op de standaard lokale executors:
<?xml version="1.0" encoding="utf-8" ?>
<Configuration xmlns="https://www.unrealengine.com/BuildConfiguration">
<BuildConfiguration>
<bAllowUBAExecutor>false</bAllowUBAExecutor>
<bAllowUBALocalExecutor>false</bAllowUBALocalExecutor>
</BuildConfiguration>
</Configuration>
Deze configuratie omzeilt UBA met succes. Echter, het volledig uitschakelen van UBA betekent dat je de aanzienlijke voordelen in compilatiesnelheid verliest die het biedt voor je primaire build-acties.
Stappenplan om de error op te lossen
Afhankelijk van je workflow kun je ervoor kiezen om dit probleem globaal op te lossen door je XML-configuratie aan te passen, of door de UBT-sourcecode direct te patchen om build acceleration te behouden voor niet-recursieve compilaties.
Methode 1: De BuildConfiguration.xml override
Als je de engine-sourcecode niet wilt aanpassen, kun je UBA globaal uitschakelen. Dit is de snelste manier om je project te compileren, hoewel het de compileertijden voor clean builds met ~40% tot ~60% zal verhogen, afhankelijk van je hardware.
- Zoek of maak je globale
BuildConfiguration.xml-bestand. Op Windows staat dit meestal in%AppData%\Roaming\Unreal Engine\UnrealBuildTool\BuildConfiguration.xml. Op Linux bevindt het zich in~/.config/Unreal Engine/UnrealBuildTool/BuildConfiguration.xml. - Open het XML-bestand in een teksteditor.
- Vervang de inhoud door het bijgewerkte XML-schema dat hieronder wordt getoond.
- Sla het bestand op en herstart je Visual Studio-build.
<?xml version="1.0" encoding="utf-8" ?>
<Configuration xmlns="https://www.unrealengine.com/BuildConfiguration">
<BuildConfiguration>
<bAllowUBAExecutor>false</bAllowUBAExecutor>
<bAllowUBALocalExecutor>false</bAllowUBALocalExecutor>
</BuildConfiguration>
</Configuration>
Methode 2: UBT-sourcecode patchen (Aanbevolen)
Aangezien je Unreal Engine 5.8 compileert vanaf source, is de aanbevolen oplossing om de UBT C#-sourcecode te patchen. Dit zorgt ervoor dat UBA kan draaien op je primaire compilatie-target, terwijl het tijdens recursieve aanroepen een fallback afdwingt naar de standaard ParallelExecutor.
- Navigeer naar de UBT-source-directory:
Engine/Source/Programs/UnrealBuildTool/Executors/. - Open het bestand
ExecutorFactory.csin Visual Studio of een teksteditor. - Zoek de
Create-methode op. Deze methode is verantwoordelijk voor het evalueren van je configuratie en het retourneren van de juisteActionExecutor. - Pas de voorwaardelijke verklaring (conditional statement) voor de UBA-selectie aan, zodat deze een controle bevat op recursieve UBT-runs.
// Engine/Source/Programs/UnrealBuildTool/Executors/ExecutorFactory.cs
public static ActionExecutor Create(BuildConfiguration BuildConfiguration, List<TargetDescriptor> TargetDescriptors, ILogger Logger)
{
// Check if UBA is allowed, available, and NOT running recursively
- if (BuildConfiguration.bAllowUBAExecutor && UBAExecutor.IsAvailable())
+ if (BuildConfiguration.bAllowUBAExecutor && UBAExecutor.IsAvailable() && !UnrealBuildTool.IsRecursive)
{
return new UBAExecutor(BuildConfiguration, Logger);
}
// Fall back to IncrediBuild if configured
if (BuildConfiguration.bAllowXGE)
{
return new XGEExecutor(BuildConfiguration, Logger);
}
// Fall back to standard ParallelExecutor
return new ParallelExecutor(BuildConfiguration, Logger);
}
Deze patch voorkomt dat de geneste UBT-instantie de UBA executor selecteert. In plaats daarvan zal de recursieve build (zoals het bouwen van UnrealHeaderTool) veilig draaien met behulp van de lokale ParallelExecutor, terwijl je primaire engine-compilatie de volledige kracht van UBA blijft benutten.
Methode 3: Command-line flags
Als je het build-proces uitvoert via custom command-line scripts of CI/CD-pipelines, kun je UBA per aanroep uitschakelen. Dit is vooral handig als je UBA ingeschakeld wilt laten voor lokale developers, maar het wilt uitschakelen op remote build-servers.
Voeg hiervoor de flag -NoUBA toe aan je UBT build-commando:
# Example command to build the editor without UBA
Engine\Build\BatchFiles\Build.bat UnrealEditor Win64 Development -NoUBA
Als alternatief kun je UBT dwingen om de standaard parallel executor te gebruiken door deze expliciet op te geven met de -Executor-flag:
Engine\Build\BatchFiles\Build.bat UnrealEditor Win64 Development -Executor=Parallel
De build-omgeving opschonen en regenereren
Na het toepassen van een van de bovenstaande oplossingen kan het zijn dat UBT niet compileert door gecachte assembly-bestanden of verouderde intermediate metadata. Om ervoor te zorgen dat de fix goed wordt toegepast, moet je de gegenereerde build tool binaries wissen en de projectbestanden regenereren.
Voor Windows-omgevingen
Voer de volgende commando's uit in een opdrachtprompt of PowerShell-venster dat naar je Unreal Engine source-directory verwijst:
:: Delete the cached UBT assembly and build binaries
rd /s /q Engine\Intermediate\Build\UnrealBuildTool
rd /s /q Engine\Binaries\DotNET\UnrealBuildTool
:: Regenerate the project files
GenerateProjectFiles.bat
Voor Linux- en macOS-omgevingen
Voer deze commando's uit in je terminal:
# Remove cached build tool data
rm -rf Engine/Intermediate/Build/UnrealBuildTool
rm -rf Engine/Binaries/DotNET/UnrealBuildTool
# Regenerate project files
./GenerateProjectFiles.sh
Zonder dat de omgeving schoon is, open je het gegenereerde solution-bestand (UE5.sln) in Visual Studio en rebuild je de target. De build zou nu de recursieve compilatiefase moeten passeren zonder de executor exception op te werpen.
Best practices voor Unreal Engine Source Builds
Het bouwen van een eigen engine-fork vanaf source brengt verschillende uitdagingen met zich mee op het gebied van compilatie, optimalisatie en packaging. Het toepassen van de volgende best practices helpt je om een stabiele en sterk geoptimaliseerde development pipeline te behouden.
1. Optimaliseer concurrency om memory starvation te voorkomen
Moderne C++ compilers vereisen aanzienlijk veel RAM per compilatie-thread. Bij het bouwen van grote engine-modules kan UBT meer parallelle taken starten dan je systeem-RAM kan ondersteunen, wat leidt tot page-file thrashing of compiler crashes.
Je kunt het maximale aantal processors beperken door de instellingen voor de ParallelExecutor te configureren in je BuildConfiguration.xml-bestand:
<Configuration xmlns="https://www.unrealengine.com/BuildConfiguration">
<ParallelExecutor>
<MaxProcessorCount>16</MaxProcessorCount>
<ProcessorCountMultiplier>1.0</ProcessorCountMultiplier>
</ParallelExecutor>
</Configuration>
Beperk het aantal tot ongeveer 2 GB RAM per thread. Een machine met 32 GB RAM zou de MaxProcessorCount bijvoorbeeld moeten beperken tot 16.
2. Beheers asset stripping voor dedicated servers
Wanneer je je game naar de cloud deployt, wil je voorkomen dat onnodige client-assets (zoals UI-textures, audio en meshes) worden meegecompileerd in de binary van je dedicated server. Dit verkort de opstarttijd en verkleint de memory footprint van je server, wat essentieel is om fleets efficiënt te schalen.
Om te leren hoe je je build-scripts configureert om deze assets uit te sluiten, kun je onze gedetailleerde handleiding over Unreal Engine Dedicated Server Asset Stripping volgen.
3. Verifieer Blueprint- en package-integriteit in een vroeg stadium
Een succesvolle engine build garandeert niet dat je project zonder fouten zal packagen. Verouderde blueprints of serialisatiefouten veroorzaken vaak crashes tijdens de uiteindelijke packaging-fase.
Om voorkomen dat deze problemen je release pipeline blokkeren, lees je onze handleiding over Resolving the Unreal Package HasValidBlueprint Ensure Crash om geautomatiseerde validatie-checks in te richten.
4. Configureer UBA VFS-caching correct
Als je besluit om UBA ingeschakeld te laten met behulp van de C#-patch, configureer dan de virtual file system cache om gecompileerde object-bestanden lokaal op te slaan. Dit voorkomt dat ongewijzigde source-bestanden opnieuw moeten worden gecompileerd bij het wisselen van branches.
Voeg het UnrealBuildAccelerator-configuratieblok toe aan je XML-bestand om caching in te schakelen:
<Configuration xmlns="https://www.unrealengine.com/BuildConfiguration">
<UnrealBuildAccelerator>
<WriteCache>true</WriteCache>
<Cache>127.0.0.1</Cache>
</UnrealBuildAccelerator>
</Configuration>
Zorg ervoor dat je firewall de lokale netwerkcommunicatiepoorten van UBA niet blokkeert, welke worden gebruikt om de cache-synchronisatieloop te beheren.
Je backend-architectuur naar een hoger niveau tillen
Het oplossen van build-problemen zoals de unreal engine uba executor ubt error is cruciaal voor het behouden van een gezonde development workflow. Het opzetten van een lokale compileer-omgeving is echter pas de eerste stap bij het bouwen van een moderne multiplayer-game.
Zodra je custom engine is gecompileerd en je dedicated servers klaar zijn, moet je de complexe uitdagingen van backend-infrastructuur aanpakken. Het vanaf nul schrijven van je eigen server-orchestratie, matchmaking-algoritmen en databases voor persistentie kost weken aan development-tijd.
Het opzetten van load balancers, database sharding en het beheer van SSL-certificaten kan gemakkelijk 4 tot 6 weken toegewijd werk kosten. Met horizOn zijn deze backend-services vooraf geconfigureerd en klaar om te schalen.
In plaats van infrastructuurcode te schrijven, kun je spelersgegevens, real-time lobby's en server-scaling integreren met een paar eenvoudige API-calls. Hierdoor kun je dedicated server-builds deployen en player state beheren met nul onderhoudsoverhead. Je team kan zich focussen op gameplay-mechanics en engine-features, terwijl horizOn de cloudinfrastructuur afhandelt.
Volgende stappen
Om deze build-fout op te lossen, kies je voor de snelle XML-override of pas je de C#-source-patch toe in ExecutorFactory.cs. Zodra je build pipeline soepel loopt, kun je kijken naar manieren om je deployment-workflow te optimaliseren. Als je je multiplayer-game wilt schalen zonder de overhead van het hosten van custom servers, probeer horizOn dan gratis of bekijk onze API-documentatie voor meer informatie.