安装
从零开始 — ILRuntime (ourpalm.github.io)
从Packages/manifest.json里添加信息后,ILRuntime在PackageManager的新的目录里面

准备热更工程
首先进入Unity主工程目录(Assets的父目录),在里面新建HotFixProject文件夹
打开Visual Studio,新建一个项目,选择“类库(.Net Framework)”,按照下图设置

框架只要选择.Net Framework 4.6.1以上即可,虽然截图中使用的是4.6.2,实际项目中使用的是4.7.2
进入工程后,将默认生成的Class1类重命名为TestClass
添加引用
在“解决方案资源管理器”中右键“引用——添加引用”,点击浏览
这里按照我的Unity编辑器安装目录,定位到几个需要引用的dll,用作参考。
| 需要引用的dll库 |
位置 |
| UnityEngine.dll(在Unity2019之后没用了) |
“D:\Program FIles\Unity Editor\2021.3.22f1c1\Editor\Data\Managed\UnityEngine.dll” |
| UnityEngine.UI.dll |
E:\UnityProjects\ResLoadPrg_Android\Library\ScriptAssemblies\UnityEngine.UI.dll |
| UnityEngine.CoreModule.dll |
D:\Program FIles\Unity Editor\2021.3.22f1c1\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.dll |
| UnityEngine.UIModule.dll |
D:\Program FIles\Unity Editor\2021.3.22f1c1\Editor\Data\Managed\UnityEngine\UnityEngine.UIModule.dll |
| Assembly-CSharp.dll |
E:\UnityProjects\ResLoadPrg_Android\Library\ScriptAssemblies\Assembly-CSharp.dll |
| Base.dll |
E:\UnityProjects\ResLoadPrg_Android\Library\ScriptAssemblies\Base.dll |
| Resource.dll |
E:\UnityProjects\ResLoadPrg_Android\Library\ScriptAssemblies\Resource.dll |
| UIManager.dll |
E:\UnityProjects\ResLoadPrg_Android\Library\ScriptAssemblies\UIManager.dll |
前面几个是Unity工程必备的dll库,后面是单独的项目中生成的dll库和Assembly Definition自己定义的dll库
在Unity2019之后UnityEngine.dll是是一个空库,它里面的功能已经拆分到了各个其他的dll中,我们这里首要引用UnityEngine.CoreModule.dll,UnityEngine这个dll库就不用了
想要定位这些dll库的位置,可以打开Unity的VS工程,在解决方案资源管理器中找到这些引用,它们的属性标记了dll库的位置。注意,自己定义的Assembly Definition的dll库Unity并不能正确标记,它指向一个缓存文件
这几个引用添加完后,记得在Visual Studio设置它们的属性,将“复制本地”设置为“False”
添加引用完成后,我们先在里面随便添加一些代码
1 2 3 4 5 6 7 8 9 10 11 12 13
| using System; using UnityEngine;
namespace HotFix { public class TestClass { public static void StaticFuncTest() { Debug.Log("Test"); } } }
|
设置Unity热更文件
在Unity工程文件夹的Assets——GameData——Data里面新建HotFix文件夹
回到HotFix工程,在Visual Studio种修改工程的属性,再点击“高级”,将“输出——调试信息”改为“可移植”。
点击“生成——生成HotFix”,快捷键Ctrl+B
这样,我们在HotFixProject——HotFix——bin——Debug文件夹内就生成了HotFix.dll和HotFix.pdb两个文件,这两个文件就是热更的主要文件,前者包含了主要逻辑,后者用来Debug。
我们要把这两个文件修改后缀后放在GameData文件夹下,这意味着这两个文件需要打成AssetBundle包,而dll后缀的文件会被Unity剔除打包,所以我们需要修改一下后缀。将HotFix.dll改为HotFix.dll.txt,将HotFix.pdb改为HotFix.pdb.txt
我们使用什么样的后缀都没关系,只要保证assetbundle会把它打包进去就好,因为dll库本质上就是一个二进制文件,ILRuntime在解释执行时也是通过读取二进制流来执行的。
点击ResFrame——Resource——ABConfig文件
在其中输入新加的HotFix文件夹路径
1 2 3
| hotfix AB Name : hotfix Path : Assets/GameData/Data/HotFix
|
如果此时Assets/GameData/Data/HotFix内有热更代码文件的话,我们打一次包,主工程目录的AssetBundle文件夹内应该能看到名为hotfix的代码ab包
主工程调用热更逻辑
在Scripts——Manager文件夹内新建ILRuntimeManager文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| using UnityEngine; using ILRuntime.Runtime.Enviorment; using System.IO;
public class ILRuntimeManager : SingletonPattern<ILRuntimeManager> { private const string DLLPATH = "Assets/GameData/Data/HotFix/Hotfix.dll.txt"; #if UNITY_EDITOR private const string PDBPATH = "Assets/GameData/Data/HotFix/Hotfix.pdb.txt"; #endif AppDomain m_AppDomain;
public void Init() { LoadHotFixAssembly(); }
void LoadHotFixAssembly() { m_AppDomain = new AppDomain(); TextAsset dllText = ResourceManager.Instance.LoadResource<TextAsset>(DLLPATH); #if UNITY_EDITOR TextAsset pdbText = ResourceManager.Instance.LoadResource<TextAsset>(PDBPATH); MemoryStream pdbms = new MemoryStream(pdbText.bytes); #endif MemoryStream dllms = new MemoryStream(dllText.bytes); #if UNITY_EDITOR m_AppDomain.LoadAssembly(dllms,pdbms,new ILRuntime.Mono.Cecil.Pdb.PdbReaderProvider()); #else m_AppDomain.LoadAssembly(dllms,null,new ILRuntime.Mono.Cecil.Pdb.PdbReaderProvider()); #endif InitializeILRuntime(); OnHotFixLoaded(); } void InitializeILRuntime() {
} void OnHotFixLoaded() { m_AppDomain.Invoke("HotFix.TestClass", "StaticFuncTest", null, null); } }
|
原视频中使用using语句来加载dllms和pdbms,但是在新版ILRuntime中,不能使用using语句了,要求加载的流不能关闭。
ILRuntime新版的用法在后面新的文章中重写。
在GameStart启动
修改GameStart的StartGame方法,添加启动ILRuntimeManager
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public IEnumerator StartGame(Image image,Text text) { image.fillAmount = 0f;
yield return null; text.text = "加载AB配置......"; AssetBundleManager.Instance.LoadAssetBundleConfig();
image.fillAmount = 0.1f; yield return null; text.text = "加载dll... ..."; ILRuntimeManager.Instance.Init(); image.fillAmount = 0.2f; yield return null; text.text = "加载配置数据... ..."; LoadConfig(); }
|
这时启动Unity,就会发现ILRuntime调用了我们热更工程的代码。
dll转换工具
每一次热更工程生成dll时,我们都需要在Unity内生成相应的热更文件,这里我们使用一个工具来转换
在Assets——Editor文件夹内新建TestEditor脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| using UnityEditor; using System.IO;
public class TestEditor { private static string DLLPATH = "E:\\UnityProjects\\ResLoadPrg_Android\\HotFixProject\\HotFix\\bin\\Debug\\Hotfix.dll"; private static string PDBPATH = "E:\\UnityProjects\\ResLoadPrg_Android\\HotFixProject\\HotFix\\bin\\Debug\\Hotfix.pdb";
private static string HotDllPath = "Assets/GameData/Data/HotFix/Hotfix.dll.txt"; private static string HotPDBPath = "Assets/GameData/Data/HotFix/Hotfix.pdb.txt"; [MenuItem("Tools/更新热更代码")] public static void ChangeDllExten() { if (File.Exists(DLLPATH)) { using(FileStream fs = new FileStream(HotDllPath,FileMode.OpenOrCreate,FileAccess.Write)) { fs.Seek(0, SeekOrigin.Begin); BinaryWriter bw = new BinaryWriter(fs); bw.Write(File.ReadAllBytes(DLLPATH)); bw.Close(); } } if(File.Exists(PDBPATH)) { using (FileStream fs = new FileStream(HotPDBPath, FileMode.OpenOrCreate, FileAccess.Write)) { fs.Seek(0, SeekOrigin.Begin); BinaryWriter bw = new BinaryWriter(fs); bw.Write(File.ReadAllBytes(PDBPATH)); bw.Close(); } } } }
|