1.1 为什么这么NB?huatuo革命Unity热更新
最近huatuo(华佗)热更新解决方案火爆了unity开发圈,起初我觉得热更新嘛,不就是内置一个脚本解释器+脚本语言开发,如xLua, ILRuntime, puerts。Huatuo又能玩出什么花样,凭什么会这么NB,引起了那么多程序员的关注与称赞呢?带着这些问题我详细的看了huatuo的资料,阅读了示例项目+huatuo源码,我也瞬间成了一位”佗粉”。接下来更新一系列的文字教程+视频教程来详细的讲解huatuo热更新。
这里有一个游戏开发交流小组,希望大家可以进去一起学习交流
要掌握huatuo热更新,我们先搞懂一些底层的概念与原理,搞懂这些是掌握huatuo的关键。本节我将从以下3个方面来详细的讲解huatuo热更新解决方案:
在说il2cpp之前,先说说mono, 在mono之前,C#虽然很好,但是只在windows家族平台上使用,就这点C#与Java就无法比。于是微软公司向ECMA申请将C#作为一种标准。在2001年12月,ECMA发布了ECMA-334 C#语言规范。C#在2003年成为一个ISO标准(ISO/IEC 23270)。意味着只要你遵守CLI(Common Language Infrastructure),第三方可以将任何一种语言实现到.Net平台之上。有了CLI的标准,Mono就诞生了, 该项目的目标是创建一系列符合ECMA标准(Ecma-334和Ecma-335)的.NET工具,包括C#编译器和通用语言架构。与微软的.NET Framework(共通语言运行平台)不同,Mono项目不仅可以运行于Windows系统上,还可以运行于Linux,FreeBSD,Unix,OS X和Solaris,甚至一些游戏平台,例如:Playstation 3,Wii或XBox 360之上。Mono使得C#这门语言相对于微软的.Net有了很好的跨平台能力。
.Net Framework运行时库Mono使用自己的Mono VM。 加上C#本身快速友好的开发能力,最终使得Unity团队在创建之初就决定将Mono,C#作为其核心。
接下来引出重要的一个概念”IL“。IL的全称是 Intermediate Language,很多时候还会看到CIL(Common Intermediate Language,特指在.Net平台下的IL标准)。在Unity中,IL和CIL表示的是同一个东西:它是一种属于通用语言架构和.NET框架的低阶(lowest-level)的编程语言。将.NET框架的语言编译成CIL,然后汇编成字节码。CIL类似一个面向对象的汇编语言,并且它是完全基于堆栈的,它运行在.net虚拟机上。
CLI标准出来后,又出现一个项目:IL2CPP,把IL转成静态的c++代码文件,由本地编译器编译成二进制机器指令。由于C#这样的高级语言都有垃圾回收等机制,所以IL转成静态的c++代码后,还有一个IL2CPP的runtime(IL2CPP VM)用来支撑这些高级语言特性。通过IL2CPP技术,我们IL代码转成本地机器码,获得很好的性能。Unity也采用了这个技术,用unity开发的C#代码可以通过.net 转成IL代码,再通过IL2CPP转成静态c++文件,然后编译成本地机器码运行。为什么Unity采用IL2CPP呢?主要原因有:
a:Mono VM在各个平台移植,维护非常耗时,有时甚至不可能完成。
b: Mono版本授权受限, 换IL2CPP,IL2CPP VM这套完全自己开发的组件,就解决了授权问题。
c: 提高运行效率,换成IL2CPP以后,程序编译成了硬件目标机器指令,运行效率提升1.5-2.0倍。
Unity基于IL2CPP 的架构原理,如图1.1-1所示:
图1.1-1
Unity IL2CPP 运行示意图
最后一个概念AOT(Ahead of time),AOT技术指的是将高级开发语言直接转成传统的编译型编程语言(如C/C++),再编译成机器指令代码在硬件上运行。IL2CPP可以成为AOT技术。
铺垫完IL2CPP,AOT等概念后,接下来就来说huatuo了。由图1.1-1可知Unity最终打包运行为:AOT(本地机器指令执行)+, IL2CPP VM(提供基础服务支撑,如gc)。对于IL2CPP 底层运行模式而言,运行的时候是数据内存对象+代码机器指令两个部分。huatuo做热更就是扩展了IL2CPP VM的服务,让它在使用原来数据内存对象的情况下,扩展了解释执行IL代码的功能(注意这里的使用”原来数据内存对象”很重要)。让IL2CPP的运行模式变为: 数据内存对象+AOT代码机器指令+Interpreter IL指令解释执行的3个部分。huatuo做热更的时候,我们只需要利用Unity ADF(asmdef, 程序集定义文件)的机制,让Unity对某一部分单独编译出一个IL指令的.dll。热更时,IL2CPP_huatuo就可以装载IL指令.dll, 由IL2CPP_huatuo来解释执行。这样AOT模式+huatuo IL指令解释执行 (Interpreter)让huatuo能具备热更新的功能。同时huatuo解释执行使用的是原来AOT的数据内存对象,所以huatuo热更新不会有其它热更新方案需要的接口导出,跨域调用等一系列问题。让开发者在不用做任何特殊处理的情况下,直接使用普通的unity开发技术能做到热更新。由于可以直接使用AOT的数据内存对象,内存占用,性能都会更好。有了这些优势(不用做任何代码上的处理就能实现热更),难怪Unity开发者都欢呼雀跃,因为他们终于能丢掉xLua, ILRuntime又笨又重的壳,直接从底层解决问题。所以我认为未来的huatuo会成为Unity热更的主流方案。
分析完原理后,我们来看下huatuo的革命性优势:
huatuo第1个优势是基于AOT(本地机器代码执行)+Interpreter (IL解释执行)使用同一个内存数据对象,没有跨域访问的问题。我们来拿xLua或ILRuntime热更方案来举例,这些方案都有一条原则,尽量减少与Unity C#层的交互,但是这种交互又避免不了而且量大,比如我们要在逻辑热更代码里面访问 Unity C#的GameObject对象数据,最终在运行的时候,GameObject 会在AOT模式下的原生内存数据结构对象。由于xLua或ILRuntime有自己的虚拟机,所以不能直接访问原生GameObject数据对象,往往要把访问里面的数据包装成函数,这样性能开销就大大的增加了。而huatuo是在IL2CPP模式下的解释执行,直接可以访问原生的数据对象。
huatuo第2个优势是我们的逻辑代码更新后(1.0版本到2.0版本),如果你发布新版本2.0(重新安装新版本的app),可以直接把更新的逻辑,直接使用AOT编译出来,不用解释执行,从而获得AOT的性能。而基于xLua, ILRuntime的热更方案开发的代码(1.0版本到2.0版本),用户即使重新安装2.0客户端后,还是解释执行,新版本的性能无法达到AOT的性能级别。
huatuo 第3个好处是相比传统的Lua或ILRuntime热更,他能更新任意部分的代码。不用像Lua或ILRuntime一样,分热更代码+框架代码,框架代码有bug还不能热更。
有了这些革命性的优势,你没有理由不关注+使用huatuo。
今天的分享就到这里了, 关注我们, 接下来会继续有huatuo热更的系列教程。
下节预告: huatuo解决方案源码结构与项目实战