|
|
2 ماه پیش | |
|---|---|---|
| .. | ||
| DirectRetrieveAttribute | 2 ماه پیش | |
| Documentation | 2 ماه پیش | |
| Editor | 2 ماه پیش | |
| MySample | 2 ماه پیش | |
| Plugins | 2 ماه پیش | |
| Runtime | 2 ماه پیش | |
| Samples | 2 ماه پیش | |
| Battle.dll | 2 ماه پیش | |
| Battle.dll.meta | 2 ماه پیش | |
| Battle.pdb | 2 ماه پیش | |
| Battle.pdb.meta | 2 ماه پیش | |
| DirectRetrieveAttribute.meta | 2 ماه پیش | |
| Documentation.meta | 2 ماه پیش | |
| Editor.meta | 2 ماه پیش | |
| LICENSE.md | 2 ماه پیش | |
| LICENSE.md.meta | 2 ماه پیش | |
| MySample.meta | 2 ماه پیش | |
| Notebook.ipynb | 2 ماه پیش | |
| Notebook.ipynb.meta | 2 ماه پیش | |
| Plugins.meta | 2 ماه پیش | |
| README.md | 2 ماه پیش | |
| README.md.meta | 2 ماه پیش | |
| Runtime.meta | 2 ماه پیش | |
| Samples.meta | 2 ماه پیش | |
| package.json | 2 ماه پیش | |
| package.json.meta | 2 ماه پیش | |
Unity注入模块,可以运行时改变被注入函数实现。
Verified Verisons:
| Unity 2021.3.x | Unity 2022.3.x |
|---|---|
| :heavy_check_mark: | :heavy_check_mark: |
开发此模块的最初动机是修改UnityEngine的源码。对这样一个具体问题一般化分析和设计后,最终实现顺便支持了用户自定义的装饰器和AOP。
Unity的注入模块已经有一些其他大神的实现了,为什么还要造一个轮子呢?原因如下:
直接修改DLL文件是可行的,但是存在以下问题:
step 1. 安装依赖库:DirectRetrieveAttribute
step 2. 通过git url安装
execute command line:
openupm add com.bbbirder.injection
一个修改Debug.Log的例子
using com.bbbirder.injection;
using UnityEngine;
// this illustration shows how to hook `Debug.Log`
public class FirstPatch
{
// the field to be overwrited to original method
static Action<object> RawLog;
static void Log(object msg){
return RawLog.Invoke("[msg] "+msg);
}
internal class MethodReplacer : IInjection
{
// implement method: ProvideInjections
public IEnumerable<InjectionInfo> ProvideInjections()
{
yield return InjectionInfo.Create<Action<object>>(
Debug.Log, // replace Debug.Log
FirstPatch.Log, // with FirstPatch.Log
f => FirstPatch.RawLog = f // save origin method to FirstPatch.RawLog
);
}
}
}
自定类继承自IInjection,并实现接口
ProvideInjections中返回一个或多个InjectionInfo
初始化的时候调用:
FixHelper.InstallAll();// 查找所有注入标记,并使生效
测试成果:
Debug.Log("hello"); //output: [msg] hello
更多使用方法参考附带的Sample工程
|Problem|Reason|Solution|
|:-:|:-|:-|
|文档示例中的异步方法无法打印完整|WebGL平台不支持多线程|文档中使用的是Task,改成UniTask或其他方式即可|
|注入时未搜索到标记的方法|Managed Stripping Level过高,Attribute被移除|降低Stripping Level或 保留代码|
|注入时报UnauthorizedAccessException或cannot access file|文件访问权限不够|管理员运行 或 修改目标文件夹的安全设置(属性-安全-编辑,添加当前用户的完全控制)|
|打包时报the same key has already been added. Key: mscorlib|不支持的Unity版本,程序集依赖树包含多个不同版本的mscorlib|暂不提供解决方案,可自行修改类型引入部分逻辑,如果这个问题影响的人多则解决之|
UnityInjection在编译时织入,不用担心运行时兼容性
织入时机:
当前的方法在Editor下也会执行织入,这将导致domain reload一定程度变慢,这对于超大代码库来说是难以忍受的。 事实上Editor下的织入不是必要的。作者忙完本职工作后,会来完善此处。
泛型的支持有一些特殊性,这种特殊性需要额外的工作: ||Inject Phase|Fix Phase| |:-|:-|:-| |AOT approach|与非泛型方法相同|-| |RT approach|不同的GenericInstance有时共享同一个方法体,有时又独享之。如:Full Generic Sharing方法存在一个共享的方法体;普通Generic Sharing则按照泛型类型内存大小共享方法体|泛型实例是运行时创建的。UnityInjection需要实现一种GenericInstantiation(classInst&methodInst)遍历的技术。这种技术对于IL2CPP backend来说,可以轻易实现;但是对于Mono backend,则需要对cctor的额外注入。|