loongly / PureScript

A C# hot reload framework for Unity3D, based on Mono's MONO_AOT_MODE_INTERP mode.
MIT License
270 stars 47 forks source link
hot-reload interpreter mono unity3d

PureScript

licensePRs Welcome

一个支持Unity3D的C#热更框架,基于Mono的MONO_AOT_MODE_INTERP模式。

支持在iOS平台Assembly.Load
构建时自动绑定Unity的Il2cpp代码。
支持大部分Unity特性,包括MonoBehaviour、Coroutine。
支持配置程序集运行环境(Il2cpp/aot/interp)
支持Cocoapods自动集成
支持对"magic code"的自定义绑定实现

iOS真机演示视频
项目介绍


iOS平台

使用“Mixed Mode Execution” 兼顾性能(aot)和灵活性(interpreter)

Windows平台

使用Jit模式运行,可以导出Il2cpp工程,添加ScriptEngine项目断点调试。

Android平台

请使用Unity的Mono运行时,可以直接调用Assembly.Load,同使用PureScript是等效的,工程结构无需修改。


使用

  1. Clone本工程,拷贝DemoProject/Assets/Plugins/PureScript目录。

  2. 修改 PureScriptBuilder.cs及ScriptEngine/Tools/config.json中的路径配置。

  3. 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也需要配置在此处
  4. ScriptEngine启动接口请参考 DemoProject\Assets\Scripts\Lancher.cs, (注意修改'reloadDir'变量)。

iOS平台

iOS平台需要安装CocoapodsNinja 。并在项目的podfile内添加PureScript引用。 例: */iOS/Podfile-example
导出xcode工程,然后

    pod install  

Windows平台

Windows平台仅用来调试,目前未添加自动集成,在构建项目后,需编译 ScriptEngine/ScriptEngine.vcxproj,替换原来Plugins目录下的的ScriptEngine.dll。
ScriptEngine.vcxproj 属性/VC++目录/包含目录中使用了宏:$(UnityEditorPath) 指向Unity/Editor目录。

调试步骤:

  1. 修改Lancher.cs中的reloadDir,替换其中的{path_to_ScriptEngine}指向PureScript\ScriptEngine\Managed目录
  2. Unity导出VS工程。
  3. 需要删除Unity导出目录下的Managed目录例如($(ExportPath)/DemoProject/Managed),否则Mono会默认从此处加载dll,Il2cpp并不会使用此目录,但是每次构建都会导出。
  4. 在导出的解决方案中添加ScriptEngine.vcxproj,并在主项目中添加ScriptEngine项目的依赖(方便调试)。
  5. 修改ScriptEngine.vcxproj中的输出目录为 $(ExportPath)/build/bin/DemoProject_Data/Plugins/,即替换原本的ScriptEngine.dll。
  6. 运行项目

例子

以下两段代码是等效的,详细参考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)

注意

  1. 需要热更新的程序集可以使用UnityEditor上的菜单PureScript/Build构建。
  2. 目前iOS平台带的mono库为arm64指令集没有开启bitcode,如有其它需求请自己构建一个替换。
  3. 如果是windows平台记得根据上面说明生成ScriptEngine.dll 替换导出目录中的dll
  4. Unity2020编辑器默认release模式导出失败,需要在编辑器右下角'Switch to debug mode'即可正常导出。
  5. 建议所有网络或文件IO操作统一在il2cpp内执行,配置为Adapter提供给Mono使用。

实现

PureScript 封装了Mono运行时,c/csharp代码生成器,pod项目自动集成,实现了两种绑定方式。两种方式均在构建时自动生成绑定代码,调用方几乎无感知,具体参考DemoProject。 两种绑定均支持调用和回调。

自动绑定过程


正式项目请将Mono库(mono.dll/mono.a) 替换为自己编译的。

如果大家对这个方案有兴趣再补充详细文档,同时欢迎提交PR或者Star。

有问题欢迎提交issue 或 loongly@foxmail.com