العودة إلى المدونة

إصلاح خطأ unreal engine uba executor ubt error في Source Builds لـ Unreal Engine 5.8

نُشر في 27 يونيو 2026
إصلاح خطأ unreal engine uba executor ubt error في Source Builds لـ Unreal Engine 5.8

باختصار

يقدم هذا الدليل حلاً مفصلاً لمشكلة خطأ البناء unreal engine uba executor ubt error الذي يظهر عند تجميع Unreal Engine 5.8 من المصدر. يستعرض المقال ثلاث طرق للتغلب على هذه المشكلة، بما في ذلك تعطيل UBA عبر ملف BuildConfiguration.xml أو ترقيع كود C# المصدري في ExecutorFactory.cs لضمان استمرارية تسريع البناء. كما يوضح الدليل خطوات تنظيف بيئة البناء وتطبيق أفضل الممارسات لتحسين استهلاك الذاكرة وتوسيع نطاق الـ Backend باستخدام خوادم Dedicated Servers.

قلة من الأشياء يمكنها تعطيل زخم الأستوديو مثل تعطل عملية بناء المحرك (engine build)، خاصةً عندما تقوم بعمل compile لنسخة Unreal Engine 5.8.0 من المصدر (source) ويتوقف Visual Studio فجأة مع استثناء (exception) غامض. يفشل البناء مع unhandled exception يشير مباشرة إلى UBAExecutor.cs. هذا العائق المحدد، والمعروف باسم unreal engine uba executor ubt error، يوقف عملية compilation تماماً. فهو يمنع الـ build graph من إكمال توليد البرامج المساعدة الحيوية مثل UnrealHeaderTool. في هذا الدليل، سنشرح بالتفصيل لماذا يواجه Unreal Build Accelerator (UBA) صعوبة في التعامل مع الـ nested calls، وكيف يفشل الإعداد الافتراضي، وكيفية ترقيع (patch) كود المحرك المصدري لاستعادة pipeline بناء يعمل بشكل صحيح.

Understanding the Build System Architecture

لفهم سبب حدوث هذا الخطأ، يجب أن نفحص كيف ينظم Unreal Build Tool (UBT) عملية compilation. قواعد الكود (codebases) الخاصة بـ Unreal Engine ضخمة للغاية، وغالباً ما تحتوي على عشرات الآلاف من ملفات المصدر. لعمل compile لهذه الملفات بكفاءة، يعمل UBT كـ meta-build system، حيث يقوم بتوليد dependency graphs وتوزيع إجراءات البناء (compile actions).

What is Unreal Build Accelerator?

قدمت Epic Games أداة Unreal Build Accelerator (UBA) كـ compilation executor افتراضي ليحل محل أنظمة التوزيع القديمة. تم تصميم UBA لتسريع عملية compilation عن طريق استخدام virtualized file system (VFS) خفيف الوزن لاعتراض عمليات I/O للملفات. ويقوم بتوجيه مهام المترجم (compiler tasks) عبر نوى المعالج المحلية المتعددة (local cores) أو توزيعها على Horde build nodes.

على جهاز بناء قياسي يحتوي على 64 نواة، يمكن لـ UBA تقليل وقت عمل clean compile للمحرك من حوالي 90 دقيقة إلى أقل من 25 دقيقة. ومع ذلك، نظراً لأن UBA يعتمد على local agent مركزي لاعتراض عمليات I/O، فإنه يتطلب تحكماً صارماً في كيفية بدء عمليات المترجم (compiler processes).

The Mechanism of Recursive UBT Calls

خلال عملية compilation، يواجه UBT بشكل متكرر targets يجب بناؤها قبل أن تتمكن ملفات المحرك الثنائية (engine binaries) الرئيسية من العمل. على سبيل المثال، قبل عمل compile لملف UnrealEditor التنفيذي، يجب على UBT عمل compile لـ UnrealHeaderTool (UHT) لتحليل ملفات الـ headers وتوليد reflection metadata.

لتحقيق ذلك، تقوم عملية UBT الرئيسية بإطلاق عملية UBT ثانوية متداخلة (nested) لبناء الـ target المطلوب مسبقاً. يُطلق على هذا الاستدعاء المتداخل اسم recursive UBT call. عندما يكون الـ recursive UBT call نشطاً، يقوم UBT بضبط flag داخلي (UnrealBuildTool.IsRecursive = true) وتمرير متغيرات البيئة (environment variables) لتمييز العملية كعملية متداخلة.

Why the UBA Executor Crashes on Recursive Invocations

يحدث الـ crash لأن الـ UBA executor غير مصمم لدعم حلقات compilation المتداخلة (nested compilation loops). لنلقِ نظرة على الـ call stack النموذجي الذي يظهره UBT عند حدوث هذا الفشل في 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

The Safety Check in UBAExecutor.cs

داخل الـ method المسمى UBAExecutor.Init (حوالي السطر 315 من UBAExecutor.cs)، يفرض المحرك صراحةً فحص أمان للتكرار (recursion safety check):

// 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...
}

يوجد فحص الأمان هذا لسبب حاسم؛ حيث يرتبط الـ local UBA agent بمنافذ TCP محددة للتواصل مع عمليات المساعد الافتراضية للمترجم (virtualized compiler helper processes).

إذا حاول استدعاء recursive UBT تهيئة نسخة ثانية من الـ UBA executor، فستحاول كلتا النسختين الارتباط بنفس منافذ الشبكة (network sockets) والتعارض حول الـ virtualized file system hooks. قد يؤدي هذا إلى أخطاء في تخصيص المنافذ (socket allocation errors)، أو تلف في نظام الملفات (filesystem corruption)، أو حالات deadlock لا نهائية في عملية البناء. هذا الـ exception يمثل حاجز حماية.

The Root Cause: Executor selection Failure

الخلل البرمجي الحقيقي (true bug) في نسخ Unreal Engine 5.8.0 المجمعة من المصدر ليس فحص الأمان هذا، بل هو فشل منطق الـ executor factory في معالجة الاستدعاءات المتداخلة (recursive calls) بشكل صحيح.

عندما يحدد UBT أي executor سيستخدمه، فإنه يستعلم من الكلاس ExecutorFactory.cs. ويتحقق الـ factory مما إذا كان UBA مفعلاً ومتاحاً على الجهاز المضيف.

ومع ذلك، فإنه لا يتحقق مما إذا كانت عملية UBT الحالية هي recursive execution أم لا. نتيجة لذلك، عندما تنطلق عملية UBT الثانوية لعمل compile لـ UnrealHeaderTool، يحاول الـ factory تعيين UBAExecutor للبناء المتداخل، مما يؤدي إلى إطلاق الـ crash في الـ method المسمى Init.

The XML Configuration Trap

يحاول العديد من المطورين تجاوز هذه المشكلة عن طريق تعديل ملف BuildConfiguration.xml العام. النصيحة القياسية في مشاركات المنتديات القديمة هي إيقاف تشغيل UBA عن طريق تعطيل الـ tag التالي:

<?xml version="1.0" encoding="utf-8" ?>
<Configuration xmlns="https://www.unrealengine.com/BuildConfiguration">
    <BuildConfiguration>
        <bAllowUBA>false</bAllowUBA>
    </BuildConfiguration>
</Configuration>

Why bAllowUBA Is Ignored in UE 5.8

إذا قمت بتطبيق إعداد XML أعلاه على نسخة Unreal Engine 5.8.0 مبنية من المصدر، فسيظل المترجم يحاول تشغيل UBA وإطلاق الاستثناء (exception). هذا لأن نظام إعدادات البناء (build configuration system) في المحرك قد تمت إعادة هيكلته (refactored).

تم إلغاء الـ flag القديم bAllowUBA ولم يعد مربوطاً بمنطق اختيار الـ executor. بدلاً من ذلك، يتم التحكم في سلوك UBA بواسطة خاصيتين مستقلتين: bAllowUBAExecutor و bAllowUBALocalExecutor.

وبما أن UBT لا يجد bAllowUBAExecutor في ملف XML الخاص بك، فإنه يفترض القيمة الافتراضية وهي true. يؤدي هذا بصمت إلى تجاوز محاولتك لإيقاف تشغيل UBA.

Correct XML Structure for UBA Configuration

لتعطيل UBA بنجاح عبر ملفات الإعدادات، يجب استخدام أسماء خصائص XML المحدثة. فيما يلي الهيكل الصحيح لإجبار UBT على التراجع إلى الـ local executors القياسيين:

<?xml version="1.0" encoding="utf-8" ?>
<Configuration xmlns="https://www.unrealengine.com/BuildConfiguration">
    <BuildConfiguration>
        <bAllowUBAExecutor>false</bAllowUBAExecutor>
        <bAllowUBALocalExecutor>false</bAllowUBALocalExecutor>
    </BuildConfiguration>
</Configuration>

يتجاوز هذا الإعداد بنجاح UBA. ومع ذلك، فإن تعطيل UBA بالكامل يعني أنك ستفقد فوائد سرعة الـ compilation الكبيرة التي يقدمها لإجراءات البناء الأساسية.

Step-by-Step Guide to Fixing the Error

اعتماداً على سير العمل (workflow) الخاص بك، يمكنك اختيار حل هذه المشكلة عالمياً عن طريق تعديل إعداد XML الخاص بك، أو عن طريق ترقيع (patching) كود UBT المصدري مباشرة للحفاظ على تسريع البناء لعمليات compilation غير المتداخلة.

Method 1: The BuildConfiguration.xml Override

إذا كنت لا ترغب في تعديل الكود المصدري للمحرك، يمكنك تعطيل UBA عالمياً. هذه هي الطريقة الأسرع لبدء بناء مشروعك، على الرغم من أنها ستزيد أوقات البناء للـ clean builds بنسبة تتراوح بين 40% إلى 60% تقريباً اعتماداً على مواصفات عتاد جهازك (hardware).

  1. حدد موقع أو قم بإنشاء ملف BuildConfiguration.xml العام. في نظام Windows، يقع هذا الملف عادةً في المسار %AppData%\Roaming\Unreal Engine\UnrealBuildTool\BuildConfiguration.xml. وفي Linux، يقع في المسار ~/.config/Unreal Engine/UnrealBuildTool\BuildConfiguration.xml.
  2. افتح ملف XML في محرر نصوص.
  3. استبدل المحتويات بـ XML schema المحدثة الموضحة أدناه.
  4. احفظ الملف وأعد تشغيل بناء Visual Studio.
<?xml version="1.0" encoding="utf-8" ?>
<Configuration xmlns="https://www.unrealengine.com/BuildConfiguration">
    <BuildConfiguration>
        <bAllowUBAExecutor>false</bAllowUBAExecutor>
        <bAllowUBALocalExecutor>false</bAllowUBALocalExecutor>
    </BuildConfiguration>
</Configuration>

Method 2: Patching UBT Source Code (Recommended)

بما أنك تقوم بعمل compile لـ Unreal Engine 5.8 من المصدر، فإن الحل الموصى به هو ترقيع (patch) الكود المصدري لـ UBT المكتوب بلغة C#. يسمح هذا لـ UBA بالعمل على الـ compilation target الرئيسي مع إجبار البناء على التراجع (fallback) إلى ParallelExecutor القياسي أثناء الـ recursive calls.

  1. انتقل إلى دليل مصدر UBT: Engine/Source/Programs/UnrealBuildTool/Executors/.
  2. افتح الملف ExecutorFactory.cs في Visual Studio أو في محرر نصوص.
  3. ابحث عن الـ Create method. هذا الـ method مسؤول عن تقييم الإعدادات الخاصة بك وإرجاع الـ ActionExecutor المناسب.
  4. قم بتعديل جملة الشرط الخاصة باختيار UBA لتشمل التحقق من تشغيل UBT بشكل تكراري (recursive 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);
}

يمنع هذا الـ patch نسخة UBT المتداخلة من تحديد الـ UBA executor. بدلاً من ذلك، سيتم تشغيل البناء التكراري (مثل بناء UnrealHeaderTool) بأمان باستخدام الـ local ParallelExecutor القياسي، بينما يستمر بناء المحرك الرئيسي في الاستفادة من القوة الكاملة لـ UBA.

Method 3: Command Line Flags

إذا كنت تقوم بتشغيل عملية البناء الخاصة بك من خلال سكريبتات سطر أوامر مخصصة أو CI/CD pipelines، يمكنك تعطيل UBA لكل عملية استدعاء على حدة. يعد هذا مفيداً بشكل خاص إذا كنت تريد إبقاء UBA مفعلاً للمطورين المحليين وتعطيله في خوادم البناء البعيدة (remote build servers).

للقيام بذلك، أضف flag المسمى -NoUBA إلى أمر بناء UBT الخاص بك:

# Example command to build the editor without UBA
Engine\Build\BatchFiles\Build.bat UnrealEditor Win64 Development -NoUBA

بدلاً من ذلك، يمكنك إجبار UBT على استخدام الـ parallel executor القياسي عن طريق تحديده صراحةً باستخدام flag المسمى -Executor:

Engine\Build\BatchFiles\Build.bat UnrealEditor Win64 Development -Executor=Parallel

Cleaning and Regenerating the Build Environment

بعد تطبيق أي من الإصلاحات المذكورة أعلاه، قد يفشل UBT في عمل compile بسبب ملفات cached assembly أو ملفات intermediate metadata القديمة. لضمان تفعيل الإصلاح بشكل نظيف، يجب عليك مسح ملفات البناء الثنائية المولدة لأداة البناء وإعادة توليد ملفات المشروع.

For Windows Environments

قم بتشغيل الأوامر التالية في نافذة command prompt أو PowerShell موجهة إلى دليل مصدر Unreal Engine الخاص بك:

:: 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

For Linux and macOS Environments

قم بتشغيل هذه الأوامر في الـ terminal الخاص بك:

# Remove cached build tool data
rm -rf Engine/Intermediate/Build/UnrealBuildTool
rm -rf Engine/Binaries/DotNET/UnrealBuildTool

# Regenerate project files
./GenerateProjectFiles.sh

بمجرد تنظيف البيئة، افتح ملف الـ solution المولد (UE5.sln) في Visual Studio وأعد بناء الـ target. يجب أن تمر عملية البناء الآن من مرحلة الـ recursive compilation دون إطلاق الـ executor exception.

Actionable Best Practices for Unreal Engine Source Builds

إن بناء custom engine fork من المصدر يفرض تحديات مختلفة تتعلق بـ compilation والتحسين (optimization) وعمل التغليف (packaging). سيساعدك تطبيق أفضل الممارسات التالية في الحفاظ على pipeline تطوير مستقر ومحسّن للغاية.

1. Optimize Concurrency to Prevent Memory Starvation

تتطلب مترجمات C++ الحديثة ذاكرة عشوائية (RAM) كبيرة لكل compilation thread. عند بناء وحدات محرك (engine modules) ضخمة، قد يقوم UBT بإطلاق مهام متوازية أكثر مما تدعمه ذاكرة النظام العشوائية (RAM)، مما يؤدي إلى حدوث page-file thrashing أو توقف المترجم عن العمل (compiler crashes).

يمكنك تحديد الحد الأقصى لعدد المعالجات عن طريق إعداد خصائص الـ ParallelExecutor في ملف BuildConfiguration.xml الخاص بك:

<Configuration xmlns="https://www.unrealengine.com/BuildConfiguration">
    <ParallelExecutor>
        <MaxProcessorCount>16</MaxProcessorCount>
        <ProcessorCountMultiplier>1.0</ProcessorCountMultiplier>
    </ParallelExecutor>
</Configuration>

قم بوضع حد أقصى للعدد بمعدل 2 جيجابايت تقريباً من الـ RAM لكل thread. على سبيل المثال، يجب على جهاز يحتوي على 32 جيجابايت من الـ RAM تحديد الـ MaxProcessorCount بـ 16.

2. Master Dedicated Server Asset Stripping

عند نشر لعبتك على السحابة (cloud)، يجب تجنب عمل compile لملفات العميل غير الضرورية (مثل UI textures والأصوات والـ meshes) داخل ملف الـ dedicated server الثنائي (dedicated server binary). يقلل هذا من أوقات تشغيل السيرفر واستهلاك الذاكرة، وهو أمر بالغ الأهمية لتوسيع نطاق الخوادم (scaling fleets) بكفاءة.

لمعرفة كيفية إعداد سكريبتات البناء الخاصة بك لاستبعاد هذه الملفات، اتبع دليلنا المفصل حول Unreal Engine Dedicated Server Asset Stripping.

3. Verify Blueprint and Package Integrity Early

بناء المحرك الناجح لا يضمن أن مشروعك سيمر بعملية packaging بدون أخطاء. غالباً ما تسبب ملفات الـ blueprints القديمة أو أخطاء الـ serialization حدوث crashes خلال مرحلة الـ packaging النهائية.

لمنع هذه المشاكل من تعطيل release pipeline الخاص بك، اقرأ دليلنا حول Resolving the Unreal Package HasValidBlueprint Ensure Crash لإعداد فحوصات تحقق تلقائية.

4. Configure UBA VFS Caching Correctly

إذا قررت إبقاء UBA مفعلاً باستخدام الـ C# patch، فقم بتهيئة الـ virtual file system cache لتخزين ملفات الـ compiled object محلياً. يتيح لك ذلك تجنب إعادة عمل compile لملفات المصدر غير المعدلة عند التنقل بين الـ branches.

أضف كتلة إعداد UnrealBuildAccelerator إلى ملف XML الخاص بك لتمكين التخزين المؤقت (caching):

<Configuration xmlns="https://www.unrealengine.com/BuildConfiguration">
    <UnrealBuildAccelerator>
        <WriteCache>true</WriteCache>
        <Cache>127.0.0.1</Cache>
    </UnrealBuildAccelerator>
</Configuration>

تأكد من أن جدار الحماية (firewall) لديك لا يحظر منافذ شبكة الاتصال المحلية الخاصة بـ UBA، والتي تُستخدم لإدارة حلقة مزامنة التخزين المؤقت (cache synchronization loop).

Elevating Your Backend Architecture

يعد حل مشكلات البناء مثل unreal engine uba executor ubt error أمراً بالغ الأهمية للحفاظ على سير عمل تطوير صحي. ومع ذلك، فإن إعداد بيئة compile محلية هو مجرد خطوة أولى في بناء لعبة Multiplayer حديثة.

بمجرد عمل compile لمحركك المخصص وتجهيز الـ Dedicated Servers الخاصة بك، يجب عليك مواجهة التحديات المعقدة لبنية الـ Backend الأساسية (backend infrastructure). إن كتابة نظام server orchestration الخاص بك، وخوارزميات Matchmaking، وقواعد البيانات الدائمة من الصفر يتطلب أسابيع من وقت التطوير.

قد يستغرق إعداد Load Balancers و database sharding وإدارة شهادات SSL بسهولة من 4 إلى 6 أسابيع من العمل المتواصل. ولكن مع horizOn، تأتي خدمات الـ Backend هذه مهيأة مسبقاً وجاهزة للتوسع (scale).

بدلاً من كتابة كود البنية التحتية، يمكنك دمج بيانات اللاعبين، والـ lobbies في الوقت الفعلي، وتوسيع نطاق السيرفرات ببعض استدعاءات الـ API البسيطة. يتيح لك ذلك نشر Dedicated Server builds وإدارة حالة اللاعبين بدون أي أعباء صيانة إضافية. يمكن لفريقك التركيز على آليات أسلوب اللعب (gameplay mechanics) وميزات المحرك بينما تتعامل horizOn مع البنية التحتية السحابية (cloud infrastructure).

Next Steps

لحل خطأ البناء هذا، اختر إما التجاوز السريع عبر XML أو قم بتطبيق الـ C# source patch في ExecutorFactory.cs. بمجرد أن يعمل build pipeline الخاص بك بسلاسة، ابحث عن طرق لتحسين سير عمل النشر (deployment workflow). إذا كنت ترغب في توسيع نطاق لعبة Multiplayer الخاصة بك دون تحمل أعباء استضافة سيرفرات مخصصة، جرب horizOn مجاناً أو راجع API documentation لمعرفة المزيد.


المصدر: Unhandled exception: Exception: UBA executor is not expected to be invoked from a recursive UBT call.