12.Unity-MonoCecil 方法重定向 初探

Cecil是一个用来生成和检查“ECMA CIL”格式的程序和类库的一个类库。用来对IL层的代码注入,达到代码重定向的作用。
通过了解MonoCecil,了解IL码写法,了解IL热更框架的原理
对于Unity方法重定向,还是更加推荐其他开源项目:
比如MonoHook,UnityHook,DotNetHook等等,找一个合适就可以。
使用MonoCecil实现方法重定向
将Test() 重定向为 Test2()
使用监视器的按钮执行Test函数

注入前的输出结果

注入后执行Test方法, 方法已经重定向到Test2()


下面展示如何实现
环境需要: Mono.Cecil.dll、Mono.Cecil.Mdb.dll、Mono.Cecil.Pdb.dl
这里直接借用ILRuntime的

XiaoCaoTest类需要放在AssemblyDef的环境中

注入逻辑
在编辑器中执行一次DoInject()
首先获取必要数据:AssemblyDefinition,TypeDefinition
获取完数据->执行注入InjectMethod
1.获取方法1(MethodDefinition)->获取方法1的IL指令
2.在指令前插入新指令: InsertBefore
输入参数->无参数->自身 -> OpCodes.Ldarg_0
调用方法2 OpCodes.Call , method2
return中断 -> OpCodes.Ret
其他函数
获取AssemblyDef
dll文件一般放在项目的 Library\ScriptAssemblies中
计算注入后的函数偏移值
必要Using补充
缺点:是在dll文件中注入,当编辑器重新编译时,dll中注入的内容会消失。需要重新注入。
而自动注入的方法也过于麻烦。
自动注入的思路:
使用[InitializeOnLoadMethod]标记配合
CompilationPipeline.assemblyCompilationFinished += CallBack
注册编译完成的回调,执行注入。
但还要注意,一个dll只能注入一次,注入多次,注入的结果会累加在dll中。
所以就需要一个变量来缓存是否已经注入过。可以在目标类加入一个标记用的方法,如果方法存在则说明注入过,不需要注入。
这类自动注入,在其他热更框架上应该都做得很好。