ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Unity热更新实践:基于HybridCLR的C#热更接入全流程解析

Unity热更新实践:基于HybridCLR的C#热更接入全流程解析 做Unity这么多年几乎每年都会遇到一次“要不要上热更新”的争论。尤其是线上Bug修复要等包体审核、版本覆盖周期长、玩家一听说又要重新下载几百兆安装包就骂娘的时候热更新几乎是绕不开的刚需。这两年C#项目的热更方案里HybridCLR属于热度确实很高的一个也是我最近几个项目里真正用到线上的方案。这篇就按实际接入流程写一遍把那些文档里没写全、论坛里问得最多的细节一起捋清楚。先说个结论HybridCLR不是银弹也并不会让项目从“不能热更”立刻变成“全能热更”但如果你团队本身就是Unity C#技术栈、不打算为了热更再引入一整套Lua流程那它确实是一条成本相对可控的路线。下面我按真实项目接入的顺序来写从方案选型、工程准备、程序集拆分、编辑器/命令行构建到运行时加载和真机问题排查全程都是我实际踩过的路子。1. 先想明白HybridCLR在热更新里到底解决什么问题1.1 为什么放着Lua不用反而选了C#热更过去Unity主流的商业热更方案无非是Lua系和ILRuntime系。Lua的优势是热更彻底、历史包袱少社区里积累了非常多的框架比如xLua、slua、tolua但缺点同样明显新功能要用Lua重写UI逻辑、战斗逻辑、网络协议全得在C#和Lua之间做胶水层团队必须养一个熟悉Lua的中间层岗位。项目一旦大起来Lua侧的卡顿定位、内存泄漏排查、编辑器联调体验都会变成持续消耗人力的点。HybridCLR的思路不一样它是基于IL2CPP的AOT编译产物在运行时用一个解释器来执行“没被AOT编译进去的那部分IL代码”。简单说你写的还是C#编译出来还是标准程序集只是主包里作为AOT编译的那部分DLL固定死了另外一套热更程序集可以后续通过网络下发。因此业务团队不用切换语言原来的C#代码风格、依赖库、甚至是同事写的烂代码风格都能无缝延续。它的运行机制一句话解释就是Unity以IL2CPP方式打包后正常C#代码会变成C再编成原生机器码这部分没法直接热更HybridCLR在启动时加载热更DLL的字节码并用内置的解释器去逐条执行这些DLL里的指令。你线上修Bug实际上是让客户端把新的HotUpdate.dll拉下来替换掉之前加载的那一份。这个思路决定了它的适用场景很清晰需要热的是C#逻辑而且你不想因此把开发模式切换成“逻辑全用脚本语言写”。但要注意如果项目追求的是“美术资源、配置表、UI图集全量线上更新”那就不是HybridCLR负责的范畴那属于AssetBundle或Addressables的资源热更体系。一般我会把它和资源热更分开看待HybridCLR负责程序集Addressables或AssetBundle负责资源和配置两者组合才能做到接近完整的热更新闭环。1.2 “热哪些、不热哪些”的边界要提前划清楚我在几个项目里见到最典型的问题是有人觉得既然上了HybridCLR所有代码都能热更于是连SDK初始化、登录协议、埋点上报这种基础底层代码都往热更程序集里塞。这其实是给自己埋雷。真实情况是HybridCLR解释执行的代码有额外性能开销你总不能把每帧循环里最热的战斗计算逻辑也全部丢进去。比较合理的划分方式大致是这样适合热更玩法逻辑、UI界面流程、任务系统、活动配置表现、常规Bug修复。尽量留在AOT主包底层网络框架、SDK桥接层、安全校验、核心战斗的伤害/寻路/物理计算、需要极致性能的算法。完全不能热更修改AOT程序集接口签名后却不一起更新主包这会导致运行时加载热更程序集后方法签名对不上直接抛MethodNotFoundException。我自己项目里的判断标准很简单改动频率高、对性能不敏感、而且出问题后需要立刻线上修复的逻辑放热更侧一年不动一次、跟平台绑定很紧、性能敏感的底层老老实实待在主包。还有一类业务也要注意支付、风控、账号体系等涉及合规校验的代码尽量不要设计成可直接通过下载替换的DLL因为热更DLL容易被离线篡改后二次打包。如果项目有强的安全需求需要额外做DLL加解密、签名校验HybridCLR本身不强制校验下载文件的合法性安全策略得自己补。2. 接入前的工程准备版本、包体和平台参数2.1 Unity版本与HybridCLR版本对应关系不同Unity版本在IL2CPP内部的代码结构差异很大HybridCLR必须针对Unity版本做适配。你不能随便在Unity 2023.2上拿支持Unity 2021.3的包直接跑哪怕勉强跑起来也极可能遇到莫名其妙的崩溃。目前我用的稳定搭配其实是Unity 2021.3 LTS或2022.3 LTS加HybridCLR的Release包这两个LTS周期长、社区案例多真遇到问题也更容易搜到解决方案。接入时建议从官方仓库的Release页面拿与当前Unity版本匹配的版本号而不是直接拉主干代码。主干代码通常对应最新的Unity预览版对还在正常发版的项目并不友好。另外有朋友习惯用UPM的方式通过Git URL直接加依赖我建议在正式立项时冻结版本号不要用不指定tag或分支的方式否则某一天同事拉代码后依赖悄悄升级打包行为突然变化排查起来会非常头大。2.2 安装HybridCLR包与对应模块安装步骤本身不难但有个前置条件很容易被忽略编辑器本身必须已经安装了IL2CPP模块。国内很多同事装Unity时图快只装了默认的Mono模块后面一打包支持IL2CPP的平台就发现缺模块还得重新跑一次Unity Hub的安装流程。确认IL2CPP模块就位后打开Package Manager选择“Add package from git URL”把HybridCLR的Unity包地址粘进去。等待编译完成菜单栏会出现HybridCLR入口。接下来打开菜单里的“HybridCLR - Installer…”这里会看到两个安装项一个是安装HybridCLR需要的初始化文件另一个是安装IL2CPP补丁。注意Installer操作会改动项目里的il2cpp目录或相关配置执行前建议先提交一遍版本管理万一补丁和某个协作插件冲突方便回滚。环境准备这一点很多人会忽略“不同平台要分别安装/生成一次”。我的建议是开发期尽量统一使用StandaloneWindows/macOS做逻辑调试真机打包Android或iOS时再切换到对应Target并重新执行安装/生成流程避免在编辑器里写完热更DLL后发现打出的Android包并不生效。这里还会牵扯到另一个高频问题就是打开项目时报“No valid Unity Editor license foundplease activate your license”。它本身不是HybridCLR引起的但团队协作换电脑后经常出现而且很多人会误以为是HybridCLR补丁破坏了许可证。遇到这类问题一般关闭Unity Hub里所有实例重新登录账号激活许可或者检查是否用了命令行批处理却没有正确传-serial和-username参数。CI打包机上尤其常见把它和HybridCLR安装顺序分开排查能省不少时间。另外国内做Android包时现在越来越多工具有最低API级别要求。有的第三方SDK会在Gradle里自动要求targetSdk提升到API 35左右或者编译期报“Minimum API level需要调整到xx”。这跟HybridCLR没有直接关系但会间接影响构建脚本。如果遇到Gradle或AGP版本提示不兼容优先去Project Settings里确认IL2CPP、ARM64、Gradle模板版本而不是回头怀疑HybridCLR补丁没装对。Android平台较稳妥的方式是单独导出Gradle工程用Android Studio验证原生层日志这样HybridCLR初始化失败、IL2CPP崩溃会有更清晰的线索。2.3 热更DLL的保存与版本管理规范HybridCLR和资源热更不一样它热更的是程序集天然对版本一致性更敏感。主包发布后服务端提供的HotUpdate.dll版本必须和主包里的启动器代码匹配。尤其是接口签名如果线上主包里的启动器只认识Hotfix.App.Main()你后发的HotUpdate.dll里已经改成Hotfix.App.Run(string arg)客户端加载时必然失败。我建议在工程里维护一个hotfix_version.txt或版本常量打包时把版本信息和DLL一起上传启动器下载DLL前先请求服务端版本号再跟本地已缓存版本比对不一样才拉新文件。这块跟Addressables的版本管理思路一致但千万别图省事让热更DLL和美术资源共用一个Bundle名否则资源刷新时把DLL覆盖了一半压缩包又没下载完整运行时会加载出损坏的程序集。3. 项目程序集拆分让热更代码从主包中彻底剥离3.1 为什么拆了“假的”热更程序集等于没拆程序集拆分是HybridCLR接入最核心的一步。如果没有把代码拆到独立的热更新程序集通常叫HotUpdate.dll或Game.Hotfix.dll而是把代码直接放在默认的Assembly-CSharp里那无论HybridCLR安装得多么成功这部分代码都会在IL2CPP阶段被编译进主包后续下发DLL时连个可以替换的目标都没有。具体操作很简单但容易犯错在Assets下新增一个文件夹比如叫Assets/HotUpdate然后右键Create - Assembly Definition生成一个asmdef文件。项目里所有希望动态更新的脚本都放进这个文件夹并让asmdef的Auto Referenced按照需求配置。需要注意主工程里的普通代码不应该反向引用这个热更程序集否则主包在编译AOT时会把这个程序集一起依赖进去绕了一圈又变成了“热更代码被主程序集引用无法真正独立替换”。为了保持依赖清晰我一般会把热更代码整理成几个内部模块但asmdef只建一个比如Game.Hotfix。模块与模块之间尽量通过接口或消息机制通信接口和数据定义放另一个纯AOT程序集里。毕竟热更程序集本身可以被整体替换内部拆太细反而会增加打包产物管理和依赖检查的复杂性。3.2 AOT主程序集如何为热更侧提供接口热更代码能直接调用的只有“主包AOT侧已经存在的程序集”。你没法在热更程序集里引用一个压根不在主包内的新DLL因为运行到那一层CLR环境中找不到这个程序集的AOT版本补元数据也无济于事。所以实际工程里应该预先规划一个公共契约库比如Game.Core.dll或Game.Shared.dll里面只放接口、常量、纯数据结构的定义由主程序和热更程序共同引用。例如// 在Game.Shared.dllAOT侧中定义 public interface IGameApp { void Loop(float deltaTime); } public class GameConfig { public static string RemoteServerRoot https://your-cdn.example.com/hotfix/; }热更侧只需要继承或实现这些接口主包启动器加载热更DLL后通过反射找到实现类再以接口方式调用。这样即使热更侧内部逻辑改动翻天覆地只要接口保持不变主包不需要跟着发版。这里有个反例我在Review代码时经常看到有人图省事把登录成功后跳转主界面的逻辑写进主程序集但UI界面预制体的点击回调又挂在热更程序集里结果主程序反向引用热更程序集直接导致整个项目编译依赖环。规范的拆分原则应该是热更侧可以引用AOT侧的库但AOT侧代码禁止引用热更侧程序集。哪怕你有绕开编译错误的技巧也尽量不要用因为它会破坏“热更程序集可独立替换”的前提。3.3 通过HybridCLR的生成功能自动处理AOT引用HybridCLR的编辑器扩展里有几个生成命令大部分项目只需要执行“HybridCLR - Generate - All”。它做的事包括扫描当前工程依赖的AOT程序集清单。生成桥接函数补全AOT泛型的调用代理解析。生成link.xml保留IL2CPP裁剪时需要保留的类型。这些生成逻辑依赖工程代码结构所以每次修改AOT侧的公共类型、泛型定义或程序集依赖后都应重新生成一遍。忘掉重新生成是最常见的“发布后突然某些泛型方法崩掉”的原因之一。热更程序集里如果大量使用ListT、DictionaryTKey,TValue或者通过反序列化组件动态创建泛型对象IL2CPP在AOT编译时并不一定会为所有可能的泛型实例化生成代码。HybridCLR提供了解释型泛型的能力但仍然需要桥接函数配合。多数情况下Generate All会自动把当前已公开的AOT类型纳入桥接范围。遇到特殊情况比如某个泛型类型是通过反射拼出来的、又不在常规类型引用链上就需要你手动在AOT侧写一个“空引用类”来标记这些类型强迫代码生成器把它们包含进去。我记得第一次接的时候完全没概念代码里大量使用JsonUtility.FromJsonDictionarystring, WeaponData()打包后跑几天没有异常一旦走到某个之前从未打开过的界面就抛ExecutionEngineException。后来才发现AOT侧没给这些反射使用到的泛型做预生成Generate All也没扫描全需要手动补标记类。这类问题非常难查因为它不像空引用那样每次必现而是要运行到特定分支才崩所以前期程序集设计和引用梳理一定要仔细。4. 接入实操打包、元数据补全与运行时加载4.1 为什么必须补充AOT程序集元数据HybridCLR解释器虽然能解释执行热更DLL里的逻辑但解释器本身也需要依赖AOT元数据来识别类型和方法。IL2CPP打包后的主包里常规的托管元数据已经被裁剪往往只剩运行必需的部分。热更代码在执行时访问一个AOT类型比如UnityEngine.GameObject或Listint如果对应的元数据信息没有准备好就会抛出TypeLoadException或FileNotFoundException。因此启动流程里必须在加载热更程序集之前先用RuntimeApi.LoadMetadataForAOTAssembly把关键的AOT程序集元数据补进去。这里不是把所有AOT程序集全加载一遍而是至少覆盖最常用的核心库通常在示例里看到的是private static readonly string[] AotDllNames { mscorlib.dll, System.dll, System.Core.dll, UnityEngine.CoreModule.dll, };如果实际工程用了System.Xml、System.Net.Http、Newtonsoft.Json等额外AOT程序集也需要在列表里补上对应DLL。这一步不完全等于“把DLL文件照搬加载”它加载的是元数据不是重新编译方法体开销相对可控但依然建议放在启动时的Loading界面之后一次性批量执行不要等到进游戏后再突然加载。4.2 编译热更DLL并打进AB包HybridCLR不会自动把你的工程代码DLL变成可直接下载的文件。实际项目里热更DLL需要先通过菜单命令或CI脚本编译出来然后作为TextAsset打进AssetBundle或者直接上传到CDN并加密。我习惯的方式是维护一个编辑器构建脚本把编译和复制流程串起来。整个流程大致为切换到目标平台Android/iOS/Windows。执行Generate All生成最新的桥接函数和link.xml。用编译命令生成热更DLL到临时目录。把DLL文件改名为.bytes或打成AB同步到本地StreamingAssets或上传CDN。最后构建主包。伪代码如下实际项目里你可以包一层CI调用using UnityEditor; using UnityEditor.Build.Reporting; public static class HybridCLRBuild { public static void BuildHotfixDll() { var target EditorUserBuildSettings.activeBuildTarget; HybridCLR.Editor.Commands.CompileDllCommand.CompileDll(target); AssetDatabase.Refresh(); } public static void BuildAssetBundle() { // 这里把 Temp/HybridCLR 下生成的 Game.Hotfix.dll // 复制到 AssetBundle 输出目录并打成 ab // 具体实现取决于项目的资源热更方案 } public static void BuildMainApp() { var report BuildPipeline.BuildPlayer( new BuildPlayerOptions { scenes new[] { Assets/Scenes/Boot.unity }, locationPathName Build/Client/Game.exe, target BuildTarget.StandaloneWindows64, options BuildOptions.None }); if (report.summary.result ! BuildResult.Succeeded) throw new System.Exception(Build failed.); } }需要注意HybridCLR热更DLL即使不改变源码因平台不同编译出的DLL也不一定通用。比如Windows和Android在同一套源码下生成的IL代码通常一致但如果你在编辑器里只执行了当前激活平台的编译然后拿着Windows下生成的DLL去打Android包通常也能跑因为IL层面差异很小。但为了严谨和避免边缘情况我仍然会每次按目标平台执行一次编译。打AB时为了兼容WebGL或微信小游戏等平台尽量将DLL作为TextAsset加载而不是直接放在StreamingAssets里用File读取后者在Web平台不支持正常工作。下载到内存后使用Assembly.Load(byte[])加载这样能规避一些平台文件系统差异。4.3 运行时加载时序与入口调用一个稳的启动流程应该按这个顺序执行更新器先检查并下载最新的热更DLL和AOT元数据DLL。加载并注册AOT元数据。加载热更程序集本体。反射或接口方式调用热更入口方法。入口方法建议设计成无参或只传一个启动上下文对象因为主包一旦发布这个入口签名就固定了。下面是典型的代码骨架using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Reflection; using HybridCLR; using UnityEngine; using UnityEngine.Networking; public class BootStrap : MonoBehaviour { private const string HotfixDllName Game.Hotfix.dll; private IEnumerator Start() { // 1. 先从远端 / 本地缓存拿到资源下载地址 // 实际项目里这里通常对接自家的资源热更SDK string hotfixDllUrl https://your-cdn.example.com/hotfix/ HotfixDllName; byte[] hotfixDllBytes null; using (UnityWebRequest req UnityWebRequest.Get(hotfixDllUrl)) { yield return req.SendWebRequest(); if (req.result ! UnityWebRequest.Result.Success) { Debug.LogError(download hotfix dll failed: req.error); yield break; } hotfixDllBytes req.downloadHandler.data; } // 2. 加载AOT元数据顺序很重要 foreach (string aotDll in AotMetadataLoader.GetAotDllNames()) { byte[] dllBytes LoadFromCacheOrStreamingAssets(aotDll); int err RuntimeApi.LoadMetadataForAOTAssembly(dllBytes, HomologousImageMode.SuperSet); if (err ! 0) { Debug.LogError($LoadMetadataForAOTAssembly failed: {aotDll}, err{err}); yield break; } } // 3. 加载热更程序集 Assembly asm Assembly.Load(hotfixDllBytes); Type appType asm.GetType(Game.Hotfix.App); if (appType null) { Debug.LogError(can not find Game.Hotfix.App in hotfix dll); yield break; } // 4. 调用热更入口 var mainMethod appType.GetMethod(Main); mainMethod?.Invoke(null, null); } }LoadMetadataForAOTAssembly返回0表示成功返回其他非零值表示对应元数据加载失败。这里常碰到“第二次重复加载同一个AOT元数据会报错”的情况所以初始化代码最好做防重入处理用一个静态布尔变量标记避免热重载或场景切换导致重复加载。需要留意的一点是下载热更DLL后不要立刻删掉缓存文件建议保存到本地可写目录。主包每次启动都先走一次本地缓存读取只有缓存不存在或版本不符时才重新下载能显著减少玩家流量消耗。每次新版本覆盖时旧的DLL文件本身虽然可以被覆盖但如果你同时对DLL做了加密或改了命名规则旧缓存文件不及时清理会白白占用玩家存储空间也会让出现问题时的定位变困难。4.4 热更入口代码如何启动整个游戏逻辑主包BootStrap完成DLL加载后热更侧需要自己负责游戏主循环的初始化。这个入口代码在项目演进中会经常变化它应该放在热更程序集内方便后续所有游戏启动流程都能被热更覆盖。一个比较稳妥的热更入口实现如下// 这段代码在 Game.Hotfix 程序集里 public static class App { public static void Main() { Debug.Log([Hotfix] App Main start); var go new GameObject([HotfixEntry]); GameLoopBehaviour loop go.AddComponentGameLoopBehaviour(); GameObject.DontDestroyOnLoad(go); // 示例加载第一个游戏场景 UnityEngine.SceneManagement.SceneManager.LoadScene(LoginScene); } }主包尽量保持精简只负责“下载资源 - 加载AOT元数据 - 加载热更DLL - 调用App.Main”之后的场景切换、UI框架初始化、网络连接建立都由热更侧驱动。这样后续迭代时哪怕要调整开场加载流程也不需要重新发布主包。5. 真机与线上常见问题排查记录5.1 崩溃或异常加载不到System.dll、mscorlib.dll这个基本可以断定是AOT元数据没加载或者加载顺序不对。一定要先加载所有AOT元数据DLL再加载热更程序集。如果热更程序集里引用了System.Core.dll中的类型而AOT元数据列表漏了System.Core那么调用到对应类型方法时会报“FileNotFoundException”或者“TypeLoadException: Could not load type … from assembly …”。解决办法是打开HybridCLR Sample项目里默认的AOT元数据清单从里面挑实际用到的加上。项目里如果用了LitJson、protobuf-net等第三方库它们的DLL通常在AOT主包里一样要往清单里加。不要图省事只加一个UnityEngine.CoreModule等真机崩溃再回溯会非常被动。5.2 找不到DllNotFoundException: slua 这类原生插件错误如果你的老项目之前基于slua或tolua开发导入HybridCLR后在新机器运行偶尔会遇到“DllNotFoundException: slua”这类异常。这通常是工程里的Lua原生插件没有正确包含在当前构建目标中跟HybridCLR本身没有关系。原因往往是构建时Platform设置不正确导致Plugins目录下的原生库没被拷贝或者HybridCLR补丁重编IL2CPP后动态库加载路径变化。可以先去Project Settings确认当前激活平台然后检查对应slua相关原生库的Platform设置。如果项目已经完全切到HybridCLR则建议把所有Lua相关脚本、原生库、初始化代码彻底移除。不要抱着“暂时留着备用”的心态运行时残留的Lua初始化会触发额外的原生库加载一旦路径不对就会在启动阶段抛出各种DllNotFound反而干扰排查。5.3 高版本Android API与IL2CPP构建环境问题现在很多项目开始把target API级别提到35左右这过程中部分开发机上的Android SDK或NDK版本老旧IL2CPP构建会间歇性失败或安装后启动崩溃。跟HybridCLR直接相关的点在于HybridCLR的IL2CPP补丁会改写libil2cpp相关原生层如果NDK版本与Unity内置的libil2cpp不兼容崩溃现场会出现在il2cpp基础设施里看起来特别像热更框架的问题。这种问题先不要急着去HybridCLR群里问把NDK版本、Gradle版本、Unity版本看一遍尽量使用Unity Hub里建议的NDK配套版本。导出Gradle工程后在Android Studio原生Logcat中查看崩溃堆栈能明显看到是libunity.so还是libil2cpp.so内部的问题。先把原生环境统一到官方支持版本再回来验证HybridCLR功能通常能迅速定位。另外Android与iOS双端要注意代码裁剪问题。AOT侧程序集如果被裁剪得太狠某些被热更代码反射使用的方法在运行时无法恢复。一般HybridCLR生成link.xml会覆盖大多数但如果你为了极致减包又自定义了额外的link.xml裁剪建议留出热更需要的AOT类型白名单。不要一上来就启用Aggressive Strip否则上线后哪个界面少个方法排查成本远大于省下的那几MB。5.4 Addressables或自定义资源管理没有正确释放导致的诡异行为HybridCLR只管程序集不管资源生命周期。很多项目在加载热更DLL后又开始用Addressables加载AB资源。热更代码里动态创建的Prefab、Texture、Material都依赖资源系统正确引用计数。滥用Addressables的LoadAssetAsync但从不Release会出现内存持续增长而且热更新后旧资源版本还可能被残留在缓存中表现为“明明更新了DLL但新逻辑显示还是旧效果”。这里建议让资源热更模块提供一个统一的资源下载并缓存接口DLL和AB走同一套版本号校验。每次热更版本提升时服务端下发新的版本清单客户端对比本地已有记录只更新变化部分。别把DLL的下载单独绕过资源管理否则后面处理补丁回滚和断点续传时非常麻烦。5.5 编辑器或打包机上的许可证与重复批处理问题有些团队做CI时为了出包会频繁调用Unity -batchmode一旦许可证激活状态异常界面会提示“No valid Unity Editor license found。please activate your license.”。以前我遇到这问题总以为是HybridCLR的Installer改变了一些文件导致后来发现多数是CI机器上多个Unity进程并发抢许可证导致激活失败。解决办法是CI里保证同一时间只有一个Unity进程执行批处理并在构建脚本最前面加一个许可证自检逻辑失败则直接退出并输出日志。6. 最后再分享一点实际操作中的体会如果你是从零接入HybridCLR我建议不要一上来就把巨型业务工程整体拆完那会非常痛苦。先拿一个小Demo工程跑通建两个程序集AOT侧一个入口方法热更侧一个简单方法打包后用本地路径下载DLL并加载能跑通后再按这个模式迁移真实业务。我第一次投入真实项目时花在“程序集循环依赖”的时间远比写加载代码多因为习惯的Mono开发思维里脚本之间互相引用很随意但一旦切到AOT/热更分离模式依赖方向必须强制统一。过程中如果某个版本在论坛里看到很多人反馈崩溃别犹豫先看看是不是版本匹配问题。HybridCLR这种跟IL2CPP深度绑定的框架版本敏感度极高换了Unity小版本甚至也会带来差异。养成习惯每次升级Unity前先确认HybridCLR是否已经有对应适配版不确认清楚就不盲目升级。毕竟程序集热更一旦生效回退成本是玩家的卸载率不值得为编辑器新特性冒险。这套接入里我认为最值得投入时间研究的是程序集拆分和AOT元数据覆盖范围而不是RuntimeApi怎么调用。前者决定你后续迭代顺不顺畅后者示例代码一大堆照着抄就能用。真机遇到诡异崩溃时多利用导出工程后的原生日志把问题拆成“HybridCLR框架问题”和“业务资源问题”两个方向排查不要因为用了HybridCLR就把所有异常都归到它头上。保持这个思路热更接入这件事会比想象中顺利很多。
返回列表