一个支持Unity3D的C#热更框架,基于Mono的MONO_AOT_MODE_INTERP模式。
支持在iOS平台Assembly.Load
构建时自动绑定Unity的Il2cpp代码。
支持大部分Unity特性,包括MonoBehaviour、Coroutine。
支持配置程序集运行环境(Il2cpp/aot/interp)
支持Cocoapods
自动集成
支持对"magic code"的自定义绑定实现
使用“Mixed Mode Execution” 兼顾性能(aot)和灵活性(interpreter)
使用Jit模式运行,可以导出Il2cpp工程,添加ScriptEngine项目断点调试。
请使用Unity的Mono运行时,可以直接调用Assembly.Load
,同使用PureScript是等效的,工程结构无需修改。
Clone本工程,拷贝DemoProject/Assets/Plugins/PureScript目录。
修改 PureScriptBuilder.cs及ScriptEngine/Tools/config.json中的路径配置。
config.json中配置运行在interpreter模式的dll(否则以aot运行),以及运行在Il2cpp运行时内的dll(一般用作Adapter)。
config.json(默认配置为Demo工程配置):
ScriptEngineDir: 指向PureScript\ScriptEngine目录
AdapterSet: 配置即要在Il2cpp又要在Mono中使用的dll,一般为一些通用插件
InterpSet: 配置需要热更的dll,否则运行在aot中
Entry: 配置Mono中入口dll,通过引用关系收集需要在Mono中运行的dll,动态load的dll也需要配置在此处
ScriptEngine启动接口请参考 DemoProject\Assets\Scripts\Lancher.cs, (注意修改'reloadDir'变量)。
iOS平台需要安装Cocoapods和Ninja 。并在项目的podfile内添加PureScript引用。
例: */iOS/Podfile-example
导出xcode工程,然后
pod install
Windows平台仅用来调试,目前未添加自动集成,在构建项目后,需编译 ScriptEngine/ScriptEngine.vcxproj,替换原来Plugins目录下的的ScriptEngine.dll。
ScriptEngine.vcxproj 属性/VC++目录/包含目录中使用了宏:$(UnityEditorPath) 指向Unity/Editor目录。
调试步骤:
以下两段代码是等效的,详细参考DemoProject/*/MonoEntry.cs。
ScriptEngine.Setup(reloadDir, "TestEntry.dll");
// equal to:
Assembly assembly = Assembly.Load("TestEntry.dll");
Type type = assembly.GetType("MonoEntry");
MethodInfo mi = type.GetMethod("Main");
var res = mi.Invoke(null, null)
注意
PureScript 封装了Mono运行时,c/csharp代码生成器,pod项目自动集成,实现了两种绑定方式。两种方式均在构建时自动生成绑定代码,调用方几乎无感知,具体参考DemoProject。 两种绑定均支持调用和回调。
Internal call 绑定:
由c/cpp实现,直接使用Unity的dll,同时把Unity的Internal call绑定到UnityEngine实现,几乎没有性能损失,调用方无需修改。
例:ScriptEngine/generated/icall_binding_gen.c。
如果碰到“Unity magic”代码自动绑定有问题,可以实现自己的绑定。
例:ScriptEngine/custom/icall_binding.c。
或者在CSharp层用Adapter绑定。
Adapter绑定: 由纯CSharp实现,分别在Mono端和Il2cpp端生成绑定代码,具有更好的兼容和灵活性。Mono运行时内的dll调用Il2cpp内的dll时用到,在config.json中配置需要运行在Il2cpp内又需要在Mono内调用的dll,构建时自动生成绑定代码,在aot执行,调用时自动替换到绑定代码,调用方无需修改。 例:DemoProject/*/AdapterTest
Marshal.GetFunctionPointerForDelegate
Marshal.GetDelegateForFunctionPointer
StripAssemblies
前/后添加了绑定调用,此处是要再Il2cpp前将已经Strip
的Assemblies拷贝出一份,并且进行Adapter绑定的代码生成。Strip
前,否则会触发Il2cpp构建错误。Strip
后,此次绑定会将已经Strip
的Assemblies拷贝出一份。build.ninja
,然后通过ninja生成ScriptEngine/aot/.a正式项目请将Mono库(mono.dll/mono.a) 替换为自己编译的。
如果大家对这个方案有兴趣再补充详细文档,同时欢迎提交PR或者Star。
有问题欢迎提交issue 或 loongly@foxmail.com