{"id":20515189,"url":"https://github.com/davidsheh/ilruntimedemo","last_synced_at":"2025-10-09T15:37:02.782Z","repository":{"id":112527588,"uuid":"190368407","full_name":"DavidSheh/ILRuntimeDemo","owner":"DavidSheh","description":"从零开始构建一个 ILRuntime 热更新工程，并简单验证 ILRuntime 的代码热更新。","archived":false,"fork":false,"pushed_at":"2019-06-05T12:27:44.000Z","size":1620,"stargazers_count":7,"open_issues_count":0,"forks_count":2,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-10-09T15:37:00.426Z","etag":null,"topics":["hotfix","ilruntime","unity3d"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/DavidSheh.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2019-06-05T09:42:42.000Z","updated_at":"2022-03-27T15:57:15.000Z","dependencies_parsed_at":"2023-03-14T07:00:42.525Z","dependency_job_id":null,"html_url":"https://github.com/DavidSheh/ILRuntimeDemo","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/DavidSheh/ILRuntimeDemo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DavidSheh%2FILRuntimeDemo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DavidSheh%2FILRuntimeDemo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DavidSheh%2FILRuntimeDemo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DavidSheh%2FILRuntimeDemo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DavidSheh","download_url":"https://codeload.github.com/DavidSheh/ILRuntimeDemo/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DavidSheh%2FILRuntimeDemo/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279001647,"owners_count":26083147,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-09T02:00:07.460Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["hotfix","ilruntime","unity3d"],"created_at":"2024-11-15T21:20:06.115Z","updated_at":"2025-10-09T15:37:02.775Z","avatar_url":"https://github.com/DavidSheh.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ILRuntime 教程\n\n**声明：本教程只是笔者在学习过程中的一些记录，用于备忘。仅供参考。**\n\n本文主要介绍从零开始构建一个 ILRuntime 热更新工程，但是不会涉及具体的热更新流程。只做一些关键步骤的说明，以及 [ILRuntime 官网教程](https://ourpalm.github.io/ILRuntime/public/v1/guide/tutorial.html)没有说明的地方，顺便记录踩过的坑。最后还简单验证了一下 ILRuntime 的代码热更新。\n\n## 前期准备\n### 环境准备\n本文所使用的工具版本：Unity 2018.3.11f1；VS 2017。\n\n### 资源准备\n[下载](https://github.com/Ourpalm/ILRuntime/releases)最新版 ILRuntime 源码和调试工具，如下图：\n\n![](./Images/01_github.png)\n\n## 构建 Unity 项目\n新建一个 Unity 项目 Client，项目文件夹放到 ILRuntimeDemo 文件夹下。然后将下载的 ILRuntime 原代码压缩包解压，并将下图中的三个文件夹拷贝到 Unity 项目的 Assets 文件夹下，同时将这些目录里面的 bin、obj、Properties 子目录和 .csproj 文件都删掉。在Assets目录里建立一个名为 csc.rsp 的文本文件，在 csc.rsp 文件中加入 -unsafe。Unity 项目目录结构如下图：\n![](./Images/02_unity_project.png)\n\n注意：在笔者使用的 Unity 版本中如果使用的是 mcs.rsp 会报警告，提示将文件名改成 csc.rsp。如果添加 csc.rsp 仍然报错的话，可以重启 Unity 试试。\n\n## 构建 Hotfix 项目\n\n### 新建 VS 项目 \n使用 vs 2017 新建一个 Hotfix 类库项目，设置如下图：\n\n![](./Images/03_vs_new.png)\n\n### 新建 libs 文件夹\n 添加 Unity 相关的类库到 Hotfix 项目中。在 Hotfix 项目中新建一个 libs 文件夹，如下图：\n\n![](./Images/04_vs_libs.png)\n\n### 拷贝类库文件\n将 Unity 安装目录 Unity2018311\\Unity\\Editor\\Data\\Managed 下的 UnityEngine.dll、UnityEngine.dll.mdb 和 UnityEngine.xml，以及 Unity2018311\\Unity\\Editor\\Data\\UnityExtensions\\Unity\\GUISystem 目录下的 UnityEngine.UI.dll、UnityEngine.UI.dll.mdb 和 UnityEngine.UI.xml 这六个文件拷贝到 libs 文件夹下。如下图：\n\n![](./Images/05_unity_libs.png)\n\n### 添加类库\n为 Hotfix 添加类库引用，将 UnityEngine.dll 和 UnityEngine.UI.dll 两个类库添加到 Hotfix 项目，并将导入的类库属性设置成不拷贝到本地。如下图：\n\n![](./Images/06_vs_add_libs_1.png)\n![](./Images/06_vs_add_libs_2.png)\n\n### 修改项目属性\n修改 Hotfix 项目属性，将类库输出路径改成 Unity 项目的 StreamingAssets 文件夹。如下图：\n![](./Images/07_vs_property_1.png)\n![](./Images/07_vs_property_2.png)\n\n## 创建脚本\n### 创建 Unity 脚本\n在 Unity 项目中新建一个脚本 Main.cs，代码如下：\n```csharp\nusing System;\nusing System.Collections;\nusing System.IO;\nusing UnityEngine;\n\npublic class Main : MonoBehaviour\n{\n    ILRuntime.Runtime.Enviorment.AppDomain appdomain;\n    void Start()\n    {\n        StartCoroutine(LoadILRuntime());\n    }\n\n    IEnumerator LoadILRuntime()\n    {\n        appdomain = new ILRuntime.Runtime.Enviorment.AppDomain();\n#if UNITY_ANDROID\n    WWW www = new WWW(Application.streamingAssetsPath + \"/Hotfix.dll\");\n#else\n        WWW www = new WWW(\"file:///\" + Application.streamingAssetsPath + \"/Hotfix.dll\");\n#endif\n        while (!www.isDone)\n            yield return null;\n        if (!string.IsNullOrEmpty(www.error))\n            Debug.LogError(www.error);\n        byte[] dll = www.bytes;\n        www.Dispose();\n#if UNITY_ANDROID\n    www = new WWW(Application.streamingAssetsPath + \"/Hotfix.pdb\");\n#else\n        www = new WWW(\"file:///\" + Application.streamingAssetsPath + \"/Hotfix.pdb\");\n#endif\n        while (!www.isDone)\n            yield return null;\n        if (!string.IsNullOrEmpty(www.error))\n            Debug.LogError(www.error);\n        byte[] pdb = www.bytes;\n        using (System.IO.MemoryStream fs = new MemoryStream(dll))\n        {\n            using (System.IO.MemoryStream p = new MemoryStream(pdb))\n            {\n                appdomain.LoadAssembly(fs, p, new Mono.Cecil.Pdb.PdbReaderProvider());\n            }\n        }\n        OnILRuntimeInitialized();\n    }\n\n    void OnILRuntimeInitialized()\n    {\n        appdomain.Invoke(\"Hotfix.Game\", \"Initialize\", null, null);\n    }\n}\n```\n\n### 在 Hotfix 项目中新建脚本\n因为 Main.cs 脚本中 `appdomain.Invoke(\"Hotfix.Game\", \"Initialize\", null, null);` 这句代码表示要调用 Hotfix 项目中 Hotfix.Game 类中的 Initialize 方法，所以 Hotfix 项目中的代码如下：\n```csharp\nusing UnityEngine;\n\nnamespace Hotfix\n{\n    public class Game\n    {\n        public static void Initialize()\n        {\n            Debug.Log(\"Initialize ...\");\n        }\n    }\n}\n```\n\n## 编译运行\n编译 Hotfix 项目，在 Unity 的 StreamingAssets 目录下会生成对应的 DLL。然后运行 Unity 就能在控制台看到打印了。\n\n## ILRuntime 调试\n官网介绍的使用方法如下：\n- 安装ILRuntime调试插件，并重新启动 VS2015 或 VS2017\n- 运行Unity工程，并保证执行过 `appdomain.DebugService.StartDebugService(56000);` 来启动调试服务器\n- 用 VisualStudio 打开热更 DLL 项目\n- 点击菜单中的 Debug-\u003eAttach to ILRuntime 按钮\n- 在弹出来的窗口中填入被调试的主机的 IP 地址以及调试服务器的端口\n- 点击 Attach 按钮后，即可像 UnityVS 一样下断点调试\n\n### 调试注意事项\n1. 要在 Unity 项目的代码里面加入 `appdomain.DebugService.StartDebugService(56000);` 代码，表示启动调试服务器。代码位置如下：\n![](./Images/08_debug.png)\n2. 调试前需要先运行 Unity 这样才能启动调试服务器。然后在 VS 菜单中点击 Debug-\u003eAttach to ILRuntime，按照官网的步骤操作即可。\n\n## 热更新验证\n### 制作 UI 预制体\n1. 创建一个 Button，并将 Canvas 重命名为 UIRoot，如下图：\n\n![](./Images/09_ui.png)\n2. 在 Main.cs 脚本中添加 OnBtnClick() 方法的代码，将 Button 的点击时间绑定到 Main.cs 脚本的 OnBtnClick() 方法，代码如下：\n```csharp\npublic void OnBtnClick()\n{\n    // 调用热更项目 Hotfix.Game 类中的 ClickBtn 方法\n    appdomain.Invoke(\"Hotfix.Game\", \"ClickBtn\", null, null);\n}\n```\n3. 创建一个 UI 预制体。如下图：  \n![](./Images/10_ui_prefab.png)\n4. 在预制体上挂一个 BaseUI 的脚本，脚本代码如下：\n```csharp\nusing UnityEngine;\nusing UnityEngine.UI;\n\npublic class BaseUI : MonoBehaviour\n{\n    public Image img;\n    public Button btn;\n    public Text text;\n}\n```\n5. 给脚本变量赋值，如下：  \n![](./Images/11_script.png)\n6. 将预制体保存在 Resources 文件夹下。\n\n### 热更代码\n1. 因为 Hotfix 要访问 Unity 项目中的 BaseUI 类，所以需要添加类库引用，类库位置和设置如下图：\n![](./Images/12_hotfix_lib_1.png)\n![](./Images/12_hotfix_lib_2.png)\n2. 在 Hotfix 项目中添加 UI 的逻辑代码，新建 UILogic.cs 类。代码如下：\n```csharp\nnamespace Hotfix\n{\n    public class UILogic\n    {\n        public UILogic(BaseUI ui)\n        {\n            ui.btn.onClick.AddListener(() =\u003e \n            {\n                ui.text.text = \"Click Button!\";\n            });\n        }\n    }\n}\n```\n3. 在 Hotfix 项目的 Game.cs 脚本中添加 ClickBtn() 方法的代码，代码如下：\n```csharp\npublic static void ClickBtn()\n{\n    Debug.Log(\"ClickBtn ...\");\n\n    // 显示 UI\n    var prefab = Resources.Load\u003cGameObject\u003e(\"UITest\");\n    var obj = GameObject.Instantiate(prefab);\n    obj.transform.SetParent(GameObject.Find(\"UIRoot\").transform);\n    obj.transform.localPosition = Vector3.zero;\n    var baseUI = obj.GetComponent\u003cBaseUI\u003e();\n    new UILogic(baseUI);\n}\n```\n4. 重新编译并生成 dll，然后运行 Unity，点击 显示UI 按钮，报错如下：\n![](./Images/13_error.png)\n5. 根据报错信息的提示，拷贝报错信息中红框内的代码到 Unity 脚本 Main.cs 中。如下图：\n![](./Images/14_delegate.png)\n6. 编辑器中测试不报错后，将工程导出成 PC 平台的 exe。双击导出的 exe 文件，运行正常。然后修改 Hotfix 项目中的 UILogic.cs 类中的代码，如下图：\n![](./Images/15_hotfix_code.png)\n7. 重新编译生成 dll，然后将生成的 Hotfix.dll 和 Hotfix.pdb 拷贝到导出 exe 的 ILRuntimeDemo_Data\\StreamingAssets 目录下，然后再重新运行 exe，发现点击 Button 按钮后，不仅显示的文字变了，背景也变成红色的了，这样就实现了代码热更新。运行效果图如下：\n\n![](./Images/16_result.png)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavidsheh%2Filruntimedemo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdavidsheh%2Filruntimedemo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavidsheh%2Filruntimedemo/lists"}