# How TEngine Loads Hot Update Assemblies at Runtime: A HybridCLR Deep Dive

> Discover how TEngine leverages HybridCLR to load hot update assemblies at runtime. Explore DLL loading, TextAsset handling, and game entry point injection.

- Repository: [ALEX/tengine](https://github.com/alex-rachel/tengine)
- Tags: deep-dive
- Published: 2026-02-24

---

**TEngine uses a HybridCLR-based workflow to load hot-update assemblies at runtime by downloading compiled DLLs as binary TextAssets, loading them via `Assembly.Load`, and injecting them into the game entry point.**

TEngine, an open-source Unity game framework maintained by alex-rachel, implements a sophisticated hot-update mechanism using HybridCLR to patch game logic without rebuilding the entire player. This system leverages runtime assembly loading to streamline the update pipeline, enabling developers to distribute code fixes as lightweight binary assets.

## The Hot Update Assembly Loading Pipeline

### Configuration and Assembly Manifest

The process begins in [`UnityProject/Assets/TEngine/Runtime/Core/UpdateSetting.cs`](https://github.com/alex-rachel/tengine/blob/main/UnityProject/Assets/TEngine/Runtime/Core/UpdateSetting.cs), where the `HotUpdateAssemblies` array defines which DLLs require hot updating. According to the source code at lines 71-74, this list typically includes assemblies like `GameProto.dll` and `GameLogic.dll`. The framework also uses `LogicMainDllName` to identify the primary game logic assembly that serves as the entry point.

### Async Asset Retrieval

Inside [`UnityProject/Assets/GameScripts/Procedure/ProcedureLoadAssembly.cs`](https://github.com/alex-rachel/tengine/blob/main/UnityProject/Assets/GameScripts/Procedure/ProcedureLoadAssembly.cs), the `LoadAssembly` coroutine (lines 78-93) iterates through the hot-update list. For each assembly name, it constructs the asset path following the pattern `Assets/AssetRaw/DLL/{name}.dll.bytes` and calls `ResourceModule.LoadAssetAsync<TextAsset>` to retrieve the binary data asynchronously.

### Runtime Assembly Instantiation

Once the asset loads, the `LoadAssetSuccess` callback (lines 97-104) receives the `TextAsset` and invokes `Assembly.Load(textAsset.bytes)` to create an in-memory assembly. The code tracks these assemblies in two ways:

- If the DLL matches `UpdateSetting.LogicMainDllName`, it stores the reference in `_mainLogicAssembly`.
- All hot-update assemblies append to `_hotfixAssemblyList` for later use.

### Entry Point Resolution and Invocation

After all assets finish loading (tracked via `_loadAssemblyComplete` when `_loadAssetCount` reaches zero at lines 122-129), the `GetMainLogicAssembly` method (lines 152-169) iterates through `AppDomain.CurrentDomain.GetAssemblies()` to locate the main logic assembly. TEngine then reflects the `GameApp` type, finds its `Entrance` method, and invokes it while passing the complete list of hot-update assemblies (lines 134-148).

### AOT Metadata Handling

When `UpdateSetting.Enable` is true, the framework calls `LoadMetadataForAOTAssembly` (lines 221-238) to load original metadata for ahead-of-time compiled assemblies. This enables the interpreter to handle missing generic methods that were stripped during the AOT compilation process.

## Critical Source Files in the Loading Chain

- **[`UnityProject/Assets/GameScripts/Procedure/ProcedureLoadAssembly.cs`](https://github.com/alex-rachel/tengine/blob/main/UnityProject/Assets/GameScripts/Procedure/ProcedureLoadAssembly.cs)**: Contains the core `ProcedureLoadAssembly` class that orchestrates the async loading, assembly instantiation, and entry point invocation.
- **[`UnityProject/Assets/TEngine/Runtime/Core/UpdateSetting.cs`](https://github.com/alex-rachel/tengine/blob/main/UnityProject/Assets/TEngine/Runtime/Core/UpdateSetting.cs)**: Defines the `HotUpdateAssemblies` array and configuration flags that control the hot-update behavior at lines 71-74.
- **[`UnityProject/Assets/TEngine/Editor/HybridCLR/BuildDLLCommand.cs`](https://github.com/alex-rachel/tengine/blob/main/UnityProject/Assets/TEngine/Editor/HybridCLR/BuildDLLCommand.cs)**: Build-time utility that copies generated hot-update DLLs into the `AssetRaw/DLL` folder used at runtime.
- **[`UnityProject/Assets/TEngine/Runtime/Core/Utility/Assembly/Utility.Assembly.cs`](https://github.com/alex-rachel/tengine/blob/main/UnityProject/Assets/TEngine/Runtime/Core/Utility/Assembly/Utility.Assembly.cs)**: Provides helper methods like `GetAssemblies` for runtime assembly discovery.

## Runtime Loading Code Example

The following simplified example demonstrates the essential loading logic found in [`ProcedureLoadAssembly.cs`](https://github.com/alex-rachel/tengine/blob/main/ProcedureLoadAssembly.cs):

```csharp
// Inside ProcedureLoadAssembly.LoadAssembly()
foreach (var hotUpdateDllName in Settings.UpdateSetting.HotUpdateAssemblies)
{
    var assetPath = $"Assets/{Settings.UpdateSetting.AssemblyTextAssetPath}/{hotUpdateDllName}{Settings.UpdateSetting.AssemblyTextAssetExtension}";
    var textAsset = await ResourceModule.LoadAssetAsync<TextAsset>(assetPath);
    var assembly = Assembly.Load(textAsset.bytes);
    _hotfixAssemblyList.Add(assembly);
}

```

After loading completes, the framework invokes the game entry point:

```csharp
// From lines 134-148 in ProcedureLoadAssembly.cs
var gameAppType = _mainLogicAssembly.GetType("GameApp");
var entranceMethod = gameAppType.GetMethod("Entrance", BindingFlags.Static | BindingFlags.Public);
entranceMethod?.Invoke(null, new object[] { _hotfixAssemblyList });

```

## Summary

- TEngine implements hot updates through **HybridCLR integration**, allowing runtime loading of compiled DLLs in IL2CPP builds.
- The **UpdateSetting** configuration file defines which assemblies participate in the hot-update cycle via the `HotUpdateAssemblies` array.
- **Assembly.Load** transforms binary TextAssets into executable code at runtime without requiring application restart.
- The **ProcedureLoadAssembly** procedure manages async asset loading, assembly tracking via `_hotfixAssemblyList`, and entry point invocation through reflection.
- Optional **AOT metadata loading** ensures compatibility with ahead-of-time compiled assemblies by providing fallback interpreter support for stripped generic methods.

## Frequently Asked Questions

### What is the role of HybridCLR in TEngine's hot update system?

HybridCLR provides the underlying technology that enables loading .NET assemblies at runtime in Unity IL2CPP builds. TEngine leverages this to load updated game logic DLLs without requiring a full application rebuild, allowing patches to be distributed as small binary assets that the engine loads via `Assembly.Load`.

### How does TEngine know which assemblies to load for hot updating?

The framework checks the `HotUpdateAssemblies` array defined in [`UnityProject/Assets/TEngine/Runtime/Core/UpdateSetting.cs`](https://github.com/alex-rachel/tengine/blob/main/UnityProject/Assets/TEngine/Runtime/Core/UpdateSetting.cs) (lines 71-74). This configurable list specifies the DLL names that the `ProcedureLoadAssembly` procedure will attempt to load from the `Assets/AssetRaw/DLL/` directory at runtime.

### Where does TEngine store the hot update DLL files before loading them?

At build time, [`BuildDLLCommand.cs`](https://github.com/alex-rachel/tengine/blob/main/BuildDLLCommand.cs) copies the compiled hot-update DLLs to `UnityProject/Assets/AssetRaw/DLL/` with a `.dll.bytes` extension. At runtime, [`ProcedureLoadAssembly.cs`](https://github.com/alex-rachel/tengine/blob/main/ProcedureLoadAssembly.cs) loads these as Unity TextAssets using `ResourceModule.LoadAssetAsync<TextAsset>` before converting them to assemblies via `Assembly.Load`.

### What happens after TEngine loads the hot update assemblies?

Once loading completes, TEngine locates the `GameApp` type within the main logic assembly and invokes its static `Entrance` method, passing the list of loaded hot-update assemblies. This transfers control to the updated game logic while maintaining references to all patched assemblies in `_hotfixAssemblyList`.