HybridCLR初探

  在以往的Unity项目热更方案中,无论是lua还是ilruntime,都是基于独立vm与原生AOT(静态编译)代码进行交互(各种wraper)。现在出现了一个全新的热更方案,HybridCLR。

  HybridCLR方案实现方式与ilruntime类似,都是对dll进行更新,都需要对dll进行解释。区别在于HybrtidCLR没有vm的概念,对于原生ATO接口就直接取函数指针进行调用,对于新增加的函数进行解释执行,所以自定义了一套IL指令的执行方法(dll中其实就是许多的IL指令结构,当然为了更高效率HybridCLR将IL指令集转换成自己的指令集)。类似:BinOpVarVarVar_Add_i4 指令的实际实现:

case HiOpcodeEnum::BinOpVarVarVar_Add_i4:
{
    uint16_t __ret = *(uint16_t*)(ip + 2);
    uint16_t __op1 = *(uint16_t*)(ip + 4);
    uint16_t __op2 = *(uint16_t*)(ip + 6);
    (*(int32_t*)(localVarBase + __ret)) = (*(int32_t*)(localVarBase + __op1)) + (*(int32_t*)(localVarBase + __op2));
    ip += 8;
    continue;
}

HybridCLR相对于lua热更方案有以下优点:

  1. 游戏中只需要编写一种代码,且与Unity自身调用效率更高(直接调用AOT代码,不需要warper)

  2. 可动态新增加数据类型(如新的MonoBehaviour而不需要重新打整包),此项HybridCLR是通过修改il2cpp工具实现的,在il2cpp执行时创建新增的元数据类型。

  unity打包后会将所有的元数据类型定义到Data\Managed\Metadata\global-metadata.dat, il2cpp默认只认这个文件中已定义的元数据类型。

const char* il2cpp::vm::GlobalMetadata::GetStringFromIndex(StringIndex index)
{
    // 新增元数据给予特殊标记
    if (huatuo::metadata::IsInterpreterIndex(index))
    {
        return huatuo::metadata::MetadataModule::GetStringFromEncodeIndex(index);
    }

    // 原始il2cpp的元数据获取
    IL2CPP_ASSERT(index <= s_GlobalMetadataHeader->stringSize);
    const char* strings = MetadataOffset<const char*>(s_GlobalMetadata, s_GlobalMetadataHeader->stringOffset, index);
    #if __ENABLE_UNITY_PLUGIN__
        if (g_get_string != NULL)
        {
            g_get_string((char*)strings, index);
        }
    #endif // __ENABLE_UNITY_PLUGIN__
        return strings;
}

  3. 调用unity接口更方便,各种泛型接口都可调用

  4. 代码调试更方便,不再需要其它额外的调试工具

那么HybridCLR有没有缺点呢?当然是有的。

  1. 如在游戏中进行代码更新,则需要重新启动游戏,因为dll不支持reload。当然我们可以在加载dll之前先处理更新来避免这个问题,但更新相关代码将不能被更新。

  2.如项目中新加了dll(打包时已定义的dll不受影响),则新的dll中的脚本不能直接挂载到prefab上(无法初始化),但可以通过代码创建这些脚本。

  3. 由于HybridCLR需要读取AOT的元数据,而这些元数据dll在裁剪后打包时可能会发生变化,这将导致出现元数据不匹配报错。例如在1.1版本生成的mcrolib.dll与1.0版本生成mcrolib.dll不一致,则将1.1版本的资源包更新给1.0的整包,将运行报错。解决办法是更新资源时特殊处理,不更新这些AOT对应的dll。不过这个问题官方说将来会解决掉。

  4. 这个热更方案很依赖官方的更新,官方需要紧跟Unity版本不断适配il2cpp工具,当然如果unity直接底层支持此方案就完美了。

综上HybridCLR热更方案确实有很大的吸引力,如后续逐渐稳定,一定会被越来越多的人使用。

参考:

  关于HybridCLR可行性的思维实验:https://zhuanlan.zhihu.com/p/528326040

  HybridCLR技术原理剖析:https://zhuanlan.zhihu.com/p/531468413

 

posted @ 2022-09-28 21:03  hghhe  阅读(2332)  评论(0编辑  收藏  举报