官方文档
什么是HybirdCLR?
HybridCLR(原名 huatuo)是一个专为 Unity 项目设计的C#热更新解决方案,它通过扩展 IL2CPP 运行时,使其支持动态加载和运行 .NET 程序集(Assembly),从而在保持高性能的同时实现代码热更新能力。
HybridCLR 最初的名字 "huatuo"(华佗) 来源于中国古代名医 华佗 的典故,寓意这个技术能像神医一样为 Unity 项目 "治病"(修复Bug) 和 "强身"(动态更新功能),而无需重新发布版本。后来为了国际化推广,项目改名为 HybridCLR:
Hybrid(混合):代表它结合了 AOT(IL2CPP) + Interpreter(解释执行) 两种模式。
CLR(Common Language Runtime):表明它是 .NET 运行时的一种扩展。
不过,很多资深开发者仍习惯称它为 "huatuo",算是一个有趣的社区梗。现在官方文档和代码库中两者都会提到,但正式名称是 HybridCLR。
核心特点
1、支持热更新
允许在运行时加载新的 .dll(如逻辑代码、修复补丁),无需重新打包或发布应用。
适用于 iOS(由于 Apple 禁止 JIT,传统热更方案如 Lua/ILRuntime 性能较低,而 HybridCLR 能提供更好的性能)。
2、基于 IL2CPP,但支持动态性
IL2CPP 原本是 AOT(提前编译),无法动态加载新代码,HybridCLR 扩展了它的能力,使其支持解释执行新代码。
3、高性能
比纯解释型方案(如 ILRuntime、Lua)更快,因为 HybridCLR 能直接运行编译后的 IL 代码,减少转换开销。
4、兼容性高
支持大部分 C# 语法(包括泛型、反射、async/await 等),比部分热更方案(如 ILRuntime)的限制更少。
5、多平台支持
使用HybridCLR技术的游戏不仅能在Android平台,也能在IOS、Consoles、WebGL等所有il2cpp支持的平台上高效运行。
和其他热更新方案的比较
特性 |
xLua |
HybridCLR |
ILRuntime |
技术 |
Lua 脚本 |
IL2CPP + 解释器 |
纯 C# 解释执行 |
性能 |
⭐⭐⭐(LuaJIT 优化后较好) |
⭐⭐⭐⭐(接近原生) |
⭐⭐(解释执行较慢) |
iOS 支持 |
✅(解释执行允许) |
✅(扩展 IL2CPP) |
✅(但性能较差) |
学习成本 |
需学 Lua |
直接使用 C# |
直接使用 C#(但有兼容限制) |
适用场景 |
业务逻辑热更 |
高性能需求、全平台热更 |
简单热更,无 iOS 高性能需求 |
HybridCLR 是目前 Unity 热更新方案中 性能最好、兼容性最强 的选择之一,特别适合 iOS 平台 或 对性能要求较高的项目。它弥补了 IL2CPP 无法动态加载代码的缺陷,同时避免了 Lua/ILRuntime 的性能问题,是当前热更新技术的重要突破。
快速上手
1、安装HybridCLR
打开Package Manager,点击左上角加号,点击Add package from git URL...,
然后填入
https://gitee.com/focus-creative-games/hybridclr_unity.git
然后点击Add
打开菜单HybridCLR/Installer...
, 点击安装
按钮进行安装。 耐心等待30s左右,安装完成后会在最后打印 安装成功
日志。
2、创建热更新模块
创建 Assets/HotUpdate
目录
在目录下 右键 Create/Assembly Definition
,创建一个名为HotUpdate
的程序集模块
3、配置HybridCLR
打开菜单 HybridCLR/Settings
, 在Hot Update Assemblies
配置项中添加HotUpdate
程序集,如下图:
4、配置IL2CPP
参考该博客的 使用IL2CPP目录下的操作步骤
5、创建热更测试相关脚本
创建ConsoleToScreen.cs
脚本
创建 Assets/ConsoleToScreen.cs
脚本类,这个脚本用于测试,它可以打印日志到屏幕上,方便定位错误。
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ConsoleToScreen : MonoBehaviour
{
const int maxLines = 50;
const int maxLineLength = 120;
private string _logStr = "";
private readonly List<string> _lines = new List<string>();
public int fontSize = 15;
void OnEnable() { Application.logMessageReceived += Log; }
void OnDisable() { Application.logMessageReceived -= Log; }
public void Log(string logString, string stackTrace, LogType type)
{
foreach (var line in logString.Split('\n'))
{
if (line.Length <= maxLineLength)
{
_lines.Add(line);
continue;
}
var lineCount = line.Length / maxLineLength + 1;
for (int i = 0; i < lineCount; i++)
{
if ((i + 1) * maxLineLength <= line.Length)
{
_lines.Add(line.Substring(i * maxLineLength, maxLineLength));
}
else
{
_lines.Add(line.Substring(i * maxLineLength, line.Length - i * maxLineLength));
}
}
}
if (_lines.Count > maxLines)
{
_lines.RemoveRange(0, _lines.Count - maxLines);
}
_logStr = string.Join("\n", _lines);
}
void OnGUI()
{
GUI.matrix = Matrix4x4.TRS(Vector3.zero, Quaternion.identity,
new Vector3(Screen.width / 1200.0f, Screen.height / 800.0f, 1.0f));
GUI.Label(new Rect(10, 10, 800, 370), _logStr, new GUIStyle() { fontSize = Math.Max(10, fontSize) });
}
}
创建主场景
- 创建默认初始场景 main.scene
- 场景中创建一个空GameObject,将ConsoleToScreen挂到上面
- 在
Build Settings
中添加main场景到打包场景列表
创建热更新脚本
创建 Assets/HotUpdate/Hello.cs
文件,代码内容如下
using System.Collections;
using UnityEngine;
public class Hello
{
public static void Run()
{
Debug.Log("Hello, HybridCLR");
}
}
创建Assets/LoadDll.cs
脚本,然后在main场景中创建一个GameObject对象,挂载LoadDll脚本。
using HybridCLR;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Networking;
public class LoadDll : MonoBehaviour
{
void Start()
{
// Editor环境下,HotUpdate.dll.bytes已经被自动加载,不需要加载,重复加载反而会出问题。
#if !UNITY_EDITOR
Assembly hotUpdateAss = Assembly.Load(File.ReadAllBytes($"{Application.streamingAssetsPath}/HotUpdate.dll.bytes"));
#else
// Editor下无需加载,直接查找获得HotUpdate程序集
Assembly hotUpdateAss = System.AppDomain.CurrentDomain.GetAssemblies().First(a => a.GetName().Name == "HotUpdate");
#endif
Type type = hotUpdateAss.GetType("Hello");
type.GetMethod("Run").Invoke(null, null);
}
}
运行main场景,屏幕上会显示 'Hello,HybridCLR',表示代码工作正常。
6、打包运行
运行菜单 HybridCLR/Generate/All
进行必要的生成操作。这一步不可遗漏!!!
将{项目根目录}/HybridCLRData/HotUpdateDlls/StandaloneWindows64(MacOS下为StandaloneMacXxx)
目录下的HotUpdate.dll复制到Assets/StreamingAssets/HotUpdate.dll.bytes
,注意,要加.bytes
后缀!!!
打开Build Settings
对话框,点击Build And Run
,打包并且运行热更新示例工程。如果打包成功,并且屏幕上显示 'Hello,HybridCLR',表示热更新代码被顺利执行!
7、测试热更新
修改Assets/HotUpdate/Hello.cs
的Run函数中Debug.Log("Hello, HybridCLR");
代码,改成Debug.Log("Hello, World");
。
运行菜单命令HybridCLR/CompileDll/ActiveBulidTarget
重新编译热更新代码。
将{项目根目录}/HybridCLRData/HotUpdateDlls/StandaloneWindows64(MacOS下为StandaloneMacXxx)
目录下的HotUpdate.dll复制替换刚才的打包输出目录的 XXX_Data/StreamingAssets/HotUpdate.dll.bytes
。
重新运行程序,会发现屏幕中显示Hello, World
,表示热更新代码生效了
至此完成热更新体验!!!