HybridCLR(代号wolong)/huatuo新一代热更新方案

这篇具有很好参考价值的文章主要介绍了HybridCLR(代号wolong)/huatuo新一代热更新方案。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

 

huatuo 现已改名 HybridCLR, 而原来的huatuo仓库由途游接着维护

本文章主要以HybridCLR仓库为例说明:focus creative games(代码哲学) · GitHub

HybridCLR(代号wolong)/huatuo新一代热更新方案

 hybridclr  仓库为核心仓库
 il2cpp_plus 仓库为改造过的il2cpp仓库添加解释核心仓库的代码指令
 hybridclr_trial 仓库为示例仓库

Unity IL2CPP 技术原理与AOT

在此之前,我们先了解下Unity的发展:

  • 阶段一: C#的出现;
            微软开发出一套符合自己的标准出来,于是在Windows系列的平台上把.net的标准开发出来,就是说我们开发者只需要开发出来符合.net 字节码的标准代码, 我们就可以让我们的代码在.net上运行起来;
  • 阶段二: Mono项目; 
            为了实现跨平台(Linux, Windows, Android,MacOS等平台), 于是就有了.net虚拟机的出现,结合.net开发环境,造就了Mono项目;
  • 阶段三: Unity采用了Mono方案实现了跨平台
  • 阶段四: IL2CPP 项目;
            为什么会出现IL2CPP 项目, Unity发现使用Mono出现了那些问题?
    a: 程序的执行效率: 编写出来的.net字节码是基于.net虚拟机上运行,再编译成二进制机器指令;
    b: 针对不同的平台,Unity就要把VM都给移植一遍,同时解决VM里面发现的bug,这非常耗时耗力。而且有些平台无法进行移植;
    c: 因为Mono的授权受限,Unity无法升级Mono版本导致一些新的C#特性无法使用;

综上所了解, Unity独自开发出了一条新技术路线就是所谓的 IL2CPP,根据官方的实验数据,换成IL2CPP以后,程序的运行效率有了1.5-2.0倍的提升;

详细介绍参考: Unity将来时:IL2CPP是什么? - 知乎

这里主要说两个知识点:

  1. 什么是IL?
    IL(Intermediage Language) 中间语言,CLR把C#,java,F#等语言编写的代码都统编译成IL,这样就可以在IL 这一层实现 所有编程语言的统一,vs将编译后的IL存储在程序集中(Dll\exe)l文件中,当打开软件的时候 CLR程序集中的IL 二次编译成机器可识别的语言。
    简单地说:在Unity中,IL和CIL表示的是同一个东西,它是一种属于通用语言架构和.net框架的低阶的编程语言
  2. 什么是CLI?
    CLI(Common Language Infrastructure)通用语言基础架构,CLI是一个开放型的技术规范,它定义了一个语言无关的跨体系结构的运行环境,这使得开发者可以用规范内定义的各种高级语言来开发软件,并且无需修正即可将软件运行在不同的计算机体系结构上.由微软、惠普和英特尔于2000年向ECMA倡议的。最终定义为Ecma335标准。
    简单地说: 特指在.net平台下的IL标准

这时候肯定说这个有什么关联吗?.net是一个程序开发、运行平台,它是CLI的实现,它是要实现让程序源跨语言开发软件、让开发出来的软件跨平台 、跨系统运行。 我画张图就懂其中的道道了

HybridCLR(代号wolong)/huatuo新一代热更新方案

 所以说,.net帮我们把在Unity中开发的C#代码转为符合IL字节码就可以在.net上运行;

那么IL2CPP与上有什么区别呢?
IL2CPP在得到中间语言IL字节码后,使用IL2CPP将他们重新变为静态的编译型语言(C语言,C++语言)C++代码,然后再由各个平台(xcode,android ndk, windows visual studio等)的C++编译器来编译我们的代码,把我们的代码编程本地的机器指令,直接在os上执行,那么效率上来看肯定比在.net解释执行嘎嘎的快了;

IL2CPP只支持AOT方式,Mono支持AOT,JIT所有方式;
Android平台支持Mono和IL2CPP的所有编译方式;
IOS只支持Mono的Full AOT模式和IL2CPP;

那么什么是AOT呢?
AOT: Ahead of time 离线编译
就是把我们的高级语言➡静态编译型语言➡直接编译成二进制机器指令;

C#作为高级语言包含了GC垃圾回收, 语法特性, 线程等服务,而 c++不提供语言层面的GC垃圾回收,那又引入了一个新的知识点IL2CPP VM;
IL2CPP VM: IL2CPP的虚拟机,个人理解是一个运行库,提供一些服务:GC垃圾回收等,利用IL2CPP编写一些库,来提供这些服务;

最终可以得出一个公式:
Unity IL2CPP =  IL2CPP编译出来的二进制指令+IL2CPP vm(GC,Thread等)

HybridCLR热更新个人理解

目前市面上主流的热更新方案:

  • Lua: 内置Lua虚拟机 + Lua代码
  • ILRuntime: 内置C#的虚拟机 + 解释执行ILRuntime;

内置虚拟机什么意思? 
自己解释执行的一个运行环境,无法直接继承Monobehaviour需要自定义封一层:跨域访问,接口导出都需要开发者自己来处理,都是一件很繁琐的事情,不符合我们标准的Unity开发(拖,拉,拽,哈哈)

HybridCLR到底做了什么事情

IL2CPP runtime环境(IL2CPP VM)编写了一个解释器,解释执行IL代码指令 + 使用的是AOT的数据内存对象

我们对比下IL2CPP和HybridCLR区别
假设: 我们先定义一个struct GameObject数据内存:

C/C++代码 
AddName(GameObject go){
        string a = "test";
        return a + go.ToString();
}

IL代码
AddName(GameObject go){
        string a = "test";
        return a + go.ToString();
}

HybridCLR代码
Extra_AddName_ILFunc(GameObject  obj){
        加载到IL指令:
        {
                定义一个string类型的变量a;
                返回 a + obj.ToString();;
        }
}

得出:
IL2CPP = 数据内存(GameObject) + 代码逻辑(二进制机器指令);
HybridCLR = 数据内存(GameObject) + 代码逻指(二进制机器指令) + IL代码指令解释执行

这就是在HybridCLR热更的项目中,我们可以随意的继承使用我们GameObject,Monobehaviour;
因为这些数据对象在编译AOT的时候,这些类型全部编译进去了;
解释执行IL的new GameObiect 和 new AOT的GameObiect对象是一摸一样的;

HybridCLR优势有哪些?

  1. 直接使用的时候我们的AOT中的内存对象,内存的占用,跨域都没有什么问题; 这点就解决了其他热更项目所无法解决的内存优化,跨域问题,意味着性能提高了
  2. 不用改变我们标准的Unity开发(拖,拉,拽)习惯
  3. 不需要额外写任何特殊代码、没有代码生成,几乎没有限制。

HybridCLR开发环境搭建

快速上手 | Focus Creative GamesFocus Creative Games是一个业内领先的专注于提供游戏行业深度技术解决方案的创新型公司。https://focus-creative-games.github.io/hybridclr/start_up/开发环境准备:

  • 支持2019.4.x、2020.3.x、2021.3.x系列LTS版本
  • Visual Studio 2019 C++ 的程序集;
  • Android NDK:
  • IL2CPP for windows: 安装好测试平台的IL2CPP
  • 安装git
  • HybridCLR环境准备:

     hybridclr  核心仓库, IL代码指令解释执行
     il2cpp_plus il2cpp补丁仓库,不含核心代码是核心代码运行的必要环境
     hybridclr_trial 仓库为示例仓库

    接下来一步步配置:

  • 打开PackageManager=>选择git url
    HybridCLR(代号wolong)/huatuo新一代热更新方案
  • 输入: GitHub - focus-creative-games/hybridclr_unity: Unity package for HybridCLR
    HybridCLR(代号wolong)/huatuo新一代热更新方案
    安装失败查看是否是缺少git环境
  • 找到Installer并安装
    HybridCLR(代号wolong)/huatuo新一代热更新方案
    HybridCLR(代号wolong)/huatuo新一代热更新方案
  • 控制台看到安装完成
    HybridCLR(代号wolong)/huatuo新一代热更新方案
  • 找到setting下热跟新dlls,里面配置所自己需要的热更新dll
    HybridCLR(代号wolong)/huatuo新一代热更新方案
    HybridCLR(代号wolong)/huatuo新一代热更新方案
    HybridCLR(代号wolong)/huatuo新一代热更新方案
    这里我简单的说下我的思路, 由自己的框架层来调用Assembly Definition文件, 我这边叫做MyGame.Runtime, 顾名思义运行时候的内置程序集不作为热更新的dll, 从这里来调用热更程序集MyGame.Logic。
  • 这里着重理解下补充元数据AOT dlls
    il2cpp在完成IL到c++代码的转换后,丢失了原始IL函数体信息, 导致无法根据泛型基类List<T>的元数据实例化出List<float>的各个成员函数实现,所以需要把MyGame.Logic中用到的值类型泛型数据提前补充到AOT里,MyGame.Logic程序就能正确识别那些值类型泛型数据。
    例如:
            List<T> where T : 值类型, 从属于System.Collections.Generic; 主dll为System.dll, 所以需要把System填写入补充元数据AOT dlls中; 这样在MyGame.Logic中加载补充元数据dll后就可以愉快的使用List<T>。

    注意:这部分补充元数据.dll
    HybridCLR(代号wolong)/huatuo新一代热更新方案
    详细内容请查阅以下文章:
    处理AOT泛型 | Focus Creative Games
    AOT泛型问题 | Focus Creative Games
  • 使用下面之前先build一次项目, 再选择all
    HybridCLR(代号wolong)/huatuo新一代热更新方案
  • iOS平台的特殊处理
    打ios包前,需要自行手动替换xcode工程中的libil2cpp.a为扩充了HybridCLR代码libil2cpp.a
  • 将 热更新 dll 和 补充元数据AOT dll 纳入项目的热更新AB资源管理系统
    参考 hybridclr_trial 中Assert\Editor\HybridCLR\BuildAssetsCommand.cs
    核心代码:
           public static void CopyAOTAssembliesToStreamingAssets()
            {
                var target = EditorUserBuildSettings.activeBuildTarget;
                string aotAssembliesSrcDir = SettingsUtil.GetAssembliesPostIl2CppStripDir(target);
                string aotAssembliesDstDir = Application.streamingAssetsPath;
    
                foreach (var dll in SettingsUtil.AOTAssemblyNames)
                {
                    string srcDllPath = $"{aotAssembliesSrcDir}/{dll}.dll";
                    if (!File.Exists(srcDllPath))
                    {
                        Debug.LogError($"ab中添加AOT补充元数据dll:{srcDllPath} 时发生错误,文件不存在。裁剪后的AOT dll在BuildPlayer时才能生成,因此需要你先构建一次游戏App后再打包。");
                        continue;
                    }
                    string dllBytesPath = $"{aotAssembliesDstDir}/{dll}.dll.bytes";
                    File.Copy(srcDllPath, dllBytesPath, true);
                    Debug.Log($"[CopyAOTAssembliesToStreamingAssets] copy AOT dll {srcDllPath} -> {dllBytesPath}");
                }
            }
    
            public static void CopyHotUpdateAssembliesToStreamingAssets()
            {
                var target = EditorUserBuildSettings.activeBuildTarget;
    
                string hotfixDllSrcDir = SettingsUtil.GetHotUpdateDllsOutputDirByTarget(target);
                string hotfixAssembliesDstDir = Application.streamingAssetsPath;
    #if NEW_HYBRIDCLR_API
                foreach (var dll in SettingsUtil.HotUpdateAssemblyFilesExcludePreserved)
    #else
                foreach (var dll in SettingsUtil.HotUpdateAssemblyFiles)
    #endif
                {
                    string dllPath = $"{hotfixDllSrcDir}/{dll}";
                    string dllBytesPath = $"{hotfixAssembliesDstDir}/{dll}.bytes";
                    File.Copy(dllPath, dllBytesPath, true);
                    Debug.Log($"[CopyHotUpdateAssembliesToStreamingAssets] copy hotfix dll {dllPath} -> {dllBytesPath}");
                }
            }
  • 如何加载dll参考:Assets\Main\LoadDll.cs
    加载热更新dll的核心语句:
    System.Reflection.Assembly.Load(BetterStreamingAssets.ReadAllBytes("Assembly-CSharp.dll.bytes"));
  • 加载补充元数据dll
    加载补充元数据dll的核心语句:
    /// <summary>
    /// 为aot assembly加载原始metadata, 这个代码放aot或者热更新都行。
    /// 一旦加载后,如果AOT泛型函数对应native实现不存在,则自动替换为解释模式执行
    /// </summary>
    private static void LoadMetadataForAOTAssemblies()
    {
        List<string> aotMetaAssemblyFiles = new List<string>()
        {
            "mscorlib.dll",
            "System.dll",
            "System.Core.dll",
        };
        /// 注意,补充元数据是给AOT dll补充元数据,而不是给热更新dll补充元数据。
        /// 热更新dll不缺元数据,不需要补充,如果调用LoadMetadataForAOTAssembly会返回错误
        /// 
        HomologousImageMode mode = HomologousImageMode.SuperSet;
        foreach (var aotDllName in aotMetaAssemblyFiles)
        {
            byte[] dllBytes = BetterStreamingAssets.ReadAllBytes(aotDllName + ".bytes");
            // 加载assembly对应的dll,会自动为它hook。一旦aot泛型函数的native函数不存在,用解释器版本代码
            LoadImageErrorCode err = RuntimeApi.LoadMetadataForAOTAssembly(dllBytes, mode);
            Debug.Log($"LoadMetadataForAOTAssembly:{aotDllName}. mode:{mode} ret:{err}");
        }
    }
    
  • 创建热更主入口脚本
    using UnityGameFramework.Runtime;
    
    namespace MyGame.Logic
    {
        public class HotfixEntry
        {
            // 不可调用,供给HybridclrComponent使用
            public static void Start()
            {
                Log.Info("<color=lime>热更新层启动.</color>");
                GameEntry.Hybridclr.UpdateCallback = Update;
                GameEntry.Hybridclr.ShutdownCallback = Shutdown;
            }
    
            // 不可调用,供给HybridclrComponent使用
            private static void Update(float elapseSeconds, float realElapseSeconds)
            {
                Log.Info("<color=lime>HotfixEntry.Update.</color>");
            }
    
            // 不可调用,供给HybridclrComponent使用
            private static void Shutdown()
            {
                Log.Info("<color=lime>HotfixEntry.Shutdown.</color>");
            }
        }
    
    }
  • 再MgGame.Runtime中写入一个启动脚本叫HybridclrCpmponent,用于启用MgGame.Logic中的主入口
/// <summary>
/// 加载热更新DLL
/// </summary>
public async void LoadHotfixDLL(GameFrameworkAction complate = null)
{
    SuccessComplate = complate;

#if !UNITY_EDITOR
    for (int i = 0; i < AssemblyUtility.HotfixAssembliesNameReadOnly.Length; i++)
    {
        Log.Warning($"加载:{AssemblyUtility.HotfixAssembliesNameReadOnly[i]}");
        TextAsset dllAsset = await GameEntry.Resource.AwaitLoadAsset<TextAsset>(AssetUtility.GetHotfixDLLAsset(AssemblyUtility.HotfixAssembliesNameReadOnly[i]));
        byte[] dllbytes = dllAsset.bytes;
        Assembly.Load(dllbytes);
    }
#endif

    StartCoroutine(HotfixStart());
}

/// <summary>
/// 开始执行热更新层代码
/// </summary>
private IEnumerator HotfixStart()
{
    yield return new WaitForEndOfFrame();
    Type logic = Utility.Assembly.GetType(AssemblyUtility.HotfixAssembliesEntryFullNameReadOnly);
    if (logic == null)
    {
        Log.Error($"-----加载失败, 未找到{AssemblyUtility.HotfixAssembliesEntryFullNameReadOnly}类-----");
        yield break;
    }

    MethodInfo entry = logic.GetMethod(AssemblyUtility.HotfixAssembliesEntryMainFuncNameReadOnly, BindingFlags.Public | BindingFlags.Static);

    yield return new WaitForEndOfFrame();
    Log.Info("Hotfix主入口加载完毕, 等待进入游戏!");
    SuccessComplate?.Invoke();
    entry.Invoke(null, null);
}

  • 最后, 遇到问题记得查看FAQ, 上例子
    HybridCLR(代号wolong)/huatuo新一代热更新方案

 

FAQ:
常见错误 | Focus Creative GamesFocus Creative Games是一个业内领先的专注于提供游戏行业深度技术解决方案的创新型公司。https://focus-creative-games.github.io/hybridclr/common_errors/#currently-selected-scripting-backend-il2cpp-is-not-installed性能报告

https://focus-creative-games.github.io/hybridclr/benchmark/https://focus-creative-games.github.io/hybridclr/benchmark/


 有兴趣的小伙伴可以关注一波

 o(* ̄▽ ̄*)ブ

HybridCLR(代号wolong)/huatuo新一代热更新方案文章来源地址https://www.toymoban.com/news/detail-438167.html

到了这里,关于HybridCLR(代号wolong)/huatuo新一代热更新方案的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Unity划时代热更方案 YooAsset+HybridCLR(wolong)(原huatuo)(六)完结篇

    开始重头戏了,我们都知道wolong是用来热更代码部分,YooAsset是热更资源部分,所以二者结合起来可以就是热更完美的解决方案。 下载wolong示例项目 用 git clone或者直接下载。 用unity打开此项目,发现这个项目菜单栏已经有HybridCLR选项了,点击该选项下方的installer…,安装。

    2024年02月06日
    浏览(32)
  • Unity 热更新 之 huatuo(HybridCLR)

    一句话说说huatuo和Hybridclr: huatuo是途游开源的,之前hybird的作者在途游,后来开源华佗,后来被途游收回,就写了hybirdCLR;  阶段1:C#发展,--- windows系列平台  ----  微软标准 .net的标准开发出来;                 只需要开发出来符合.net字节码的标准代码,就可以让代码在

    2024年02月10日
    浏览(24)
  • 1.5 新一代信息技术

    战略性新兴产业是以重大技术突破和重大发展需求为基础,对经济社会全局和长远发展具有重大引领带动作用,知识技术密集、物质资源消耗少、成长潜力大、综合效益好的产业。 依据《国务院关于加快培育和发展战略性新兴产业的决定》(国发(2010) 32号),七个战略性新兴产

    2023年04月08日
    浏览(46)
  • 新一代硬件安全:第一章-简介

    Chapter 1 Introduction 1.1 Fundamentals of Hardware Security In our modern age of omnipresent and highly interconnected information technology, cybersecurity becomes ever more challenged. For example, with the rise of the Internet of Things (IoT), most such equipment is connected to the internet in some way, often inscrutable to the regular customers. This f

    2024年02月12日
    浏览(45)
  • No.14新一代信息技术

    新一代信息技术产业包括:加快建设宽带、泛在、融合、安全的信息忘了基础设施,推动新一代移动通信、下一代互联网核心设备和智能终端的研发及产业化,加快推进三网融合,促进物联网、云计算的研发和示范应用。 大数据、云计算、互联网+、物联网、智慧城市等是新

    2024年02月09日
    浏览(36)
  • 云计算:新一代的技术革命

    云计算,作为21世纪的一项重要技术革命,已在全球范围内引发了深远的影响。它改变了我们存储和处理数据的方式,使得企业无需再建设和维护昂贵的本地服务器和数据中心。本文将深入探讨云计算的基本概念,类型,主要优点,以及它在未来可能的发展趋势。 云计算的基

    2024年02月12日
    浏览(38)
  • 新一代通信协议 - Socket.D

    一、简介 Socket.D 是一种二进制字节流传输协议,位于 OSI 模型中的5~6层,底层可以依赖 TCP、UDP、KCP、WebSocket 等传输层协议。由 Noear 开发。支持异步流处理。其开发背后的动机是用开销更少的协议取代超文本传输协议(HTTP),HTTP 协议对于许多任务(如微服务通信)来说效率低下。

    2024年01月20日
    浏览(50)
  • Flink CDC 新一代数据集成框架

    前言: 主要讲解了技术原理,入门与生产实践,主要功能:全增量一体化数据集成、实时数据入库入仓、最详细的教程。Flink CDC 是Apache Flink的一个重要组件,主要使用了CDC技术从各种数据库中获取变更流并接入到Flink中,Apache Flink作为一款非常优秀的流处理引擎,其SQL API又

    2024年02月13日
    浏览(43)
  • 字节跳动新一代云原生消息队列实践

    作者:火山引擎云原生计算研发工程师|雷丽媛 上文我们了解了在字节跳动内部业务快速增长的推动下,经典消息队列 Kafka 的劣势开始逐渐暴露,在弹性、规模、成本及运维方面都无法满足业务需求。因此字节消息队列团队研发了计算存储分离的 云原生 消息引擎 BMQ ,在极

    2024年02月20日
    浏览(53)
  • 新一代自动化测试神器Playwright

    转载请注明出处❤️ 作者:测试蔡坨坨 原文链接:caituotuo.top/4bedb73c.html 你好,我是测试蔡坨坨。 说到WebUI自动化测试,首当其冲的当属Selenium,在很长的一段时间内,Selenium统治着Web自动化,Selenium其实经历了四个阶段,从2006年发布的Selenium 1.0到最新的Selenium 4.8.3。 2006年,

    2023年04月15日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包