Unity3D 想必你们都不陌生,独立游戏制做者们不少人都在用它,甚至一些大公司也用在很商业的游戏制做上。Unity3D最大的一个特色是一次制做,多平台部署,而 这一核心功能是靠Mono实现的。能够说Mono是Unity3D核心的核心,是Unity3D跨平台的根本。可是在2014年年中的时 候,Unity3D官方博客上却发了一篇“The future of scripting in unity”的文章,引出了IL2CPP的概念,感受有取代Mono之势。那什么是IL2CPP,它能为Unity3D和做为使用Unity3D的咱们带来哪些好处和改变?这就是本文尝试说明的。
C#,.Net Framework
我 们先说说IL2CPP试图取代的Mono。在说Mono以前,不得不提C#语言和背后的.Net Framework。C#是微软推出的一种基于.NET框架的、面向对象的高级编程语言。C#的发音为“see sharp”,模仿音乐上的音名“C♯”(C调升),是C语言的升级的意思。其正确写法应和音名同样为“C♯”。C#由C语言和C++派生而来,继承了其 强大的性能,同时又以.NET框架类库做为基础,拥有相似Visual Basic的快速开发能力。C#由安德斯·海尔斯伯格主持开发,微软在2000年发布了这种语言。说到安德斯·海尔斯伯格这里要多说一句,当年和VC(注 意,是VC,那个时候尚未Visual Studio)齐名还有另一家公司的IDE也很是流行,那就是Borland公司的Delphi,也是由安德斯·海尔斯伯格主导开发的。
他 后来被微软挖走,建立了J++,一门相似Java的语言(好吧,以我肤浅的知识认为,那基本就是照着Java作的)。后来因为和Sun公司受权的缘由,微 软在2001年中止了J++的开发而推出了C# 1.0。说来要感谢和Sun的这场官司,不然微软也不会有C#,J++也可能一直会跟随Java的脚步。相反C#通过不断的进化,从1.0开始到4.0和 最新的5.0,C#已经远远甩开Java几条街了(仍是以我我的的使用Java和C#感受而言,关于两门语言的比较,不管是效率上,夸平台上,仍是语言易 用性上,社区活跃度上,网上的争论随处可见,每一个人都有本身的见解,这也不是本文的重点)。
Mono,Mono VM
C#虽好,可是只能在Windows上运行,微软那时候也没有将其开源,因此老是会有人说不能跨平台,光就这点,C#和Java就不能比呀。
微 软公司已经向ECMA申请将C#做为一种标准。在2001年12月,ECMA发布了ECMA-334 C#语言规范。C#在2003年成为一个ISO标准(ISO/IEC 23270)。这意味着只要你遵照CLI(Common Language Infrastructure),第三方能够将任何一种语言实现到.Net平台之上。Mono就是在这种环境下诞生的。
Mono是一个由 Xamarin公司(先前是Novell,最先为Ximian)所主持的自由开放源代码项目。该项目的目标是建立一系列符合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 Framework运行时库Mono使用本身的Mono VM做为运行时库。 加上C#自己快速友好的开发能力,最终使得Unity团队在建立之初就决定将Mono,C#做为其核心。(嗯,这是我猜的)
有 人也许会说,Unity还支持JavaScript和Boo呢,不光光只有C#一门语言。首先我要纠正的是,在Unity中的JavaScript严格意 义上说并非W3C规范中的JavaScript,它正确的名字叫作Unity Script,实际上是从Boo演变过来的(这样你们就能理解为啥在3门语言中,Boo用的人最少,可是却还一直存在的缘由了吧)。我认为是Unity开始 为了让更多的人可以快速的上手,特别是考虑到不少脚本程序员对JavaScript已经很熟悉了,为了照顾这部分人,发明了Unity Script,它的语法和W3C的JavaScript几乎一致,使得你们能够直接用其进行开发,下降门槛。可是Unity Script在运行上却和JavaScript有着本质的不一样。这个我会在下一节IL中进行详细的描述。从三门语言在Unity中的使用状况而言:Boo 几乎就没人用了,Unity Script和C#二者中不管是演示代码仍是Unity Asset Store中的第三方代码,C#已经有85%-90%的比例(我的粗略估计,没有作详细统计)。可见C#在Unity中深受我等游戏码农的爱戴。
IL
啰 嗦完了C#,.Net Framework和Mono,引出了咱们很重要的一个概念”IL“。IL的全称是 Intermediate Language,不少时候还会看到CIL(Common Intermediate Language,特指在.Net平台下的IL标准)。在Unity博客和本文中,IL和CIL表示的是同一个东西:翻译过来就是中间语言。它是一种属于 通用语言架构和.NET框架的低阶(lowest-level)的人类可读的编程语言。目标为.NET框架的语言被编译成CIL,而后汇编成字节码。 CIL相似一个面向对象的汇编语言,而且它是彻底基于堆栈的,它运行在虚拟机上(.Net Framework, Mono VM)的语言。
具体过程是:C#或者VB这样遵循CLI规范的高级语言,被先被各自的编译器编译成中间语言:IL(CIL),等到须要真正执行的时候,这些IL会被加载到运行时库,也就是VM中,由VM动态的编译成汇编代码(JIT)而后在执行。c++
正是因为引入了VM,才使得不少动态代码特性得以实现。经过VM咱们甚至能够由代码在运行时生成新代码并执行。这个是静态编译语言所没法作到的。回到上一 节我说的Boo和Unity Script,有了IL和VM的概念咱们就不难发现,这二者并无对应的VM虚拟机,Unity中VM只有一个:Mono VM,也就是说Boo和Unity Script是被各自的编译器编译成遵循CLI规范的IL,而后再由Mono VM解释执行的。这也是Unity Script和JavaScript的根本区别。JavaScript是最终在浏览器的JS解析器中运行的(例如大名鼎鼎的Google Chrome V8引擎),而Unity Script是在Mono VM中运行的。本质上说,到了IL这一层级,它是由哪门高级语言建立的也不是那么重要了,你能够用C#,VB,Boo,Unity Script甚至C++,只要有相应的编译器可以将其编译成IL都行!
IL2CPP, IL2CPP VM
本 文的主角终于出来了:IL2CPP。有了上面的知识,你们很容易就理解其意义了:把IL中间语言转换成CPP文件。你们若是看明白了上面动态语言的 CLI, IL以及VM,再看到IL2CPP必定心中充满了疑惑。如今的大趋势都是把语言加上动态特性,哪怕是c++这样的静态语言,也出现了适合IL的c++编译 器,为啥Unity要反其道而行之,把IL再弄回静态的CPP呢?这不是吃饱了撑着嘛。根据本文最前面给出的Unity官方博客所解释的,缘由有如下几 个:
1.Mono VM在各个平台移植,维护很是耗时,有时甚至不可能完成
Mono的跨平台是经过Mono VM实现的,有几个平台,就要实现几个VM,像Unity这样支持多平台的引擎,Mono官方的VM确定是不能知足需求的。因此针对不一样的新平 台,Unity的项目组就要把VM给移植一遍,同时解决VM里面发现的bug。这很是耗时耗力。这些能移植的平台还好说,还有好比WebGL这样基于浏览 器的平台。要让WebGL支持Mono的VM几乎是不可能的。
2.Mono版本受权受限
你们有没有意识到Mono的版本已经更新到3.X了,可是在Unity中,C#的运行时版本一直停留在2.8,这也是Unity社区开发者抱怨的最多一 条:不少C#的新特性没法使用。这是由于Mono 受权受限,致使Unity没法升级Mono。若是换作是IL2CPP,IL2CPP VM这套彻底本身开发的组件,就解决了这个问题。
3.提升运行效率
根据官方的实验数据,换成IL2CPP之后,程序的运行效率有了1.5-2.0倍的提高。
使用Mono的时候,脚本的编译运行以下图所示:程序员
简单的来讲,3大脚本被编译成IL,在游戏运行的时候,IL和项目里其余第三方兼容的DLL一块儿,放入Mono VM虚拟机,由虚拟机解析成机器码,而且执行
IL2CPP作的改变由下图红色部分标明: 编程
在获得中间语言IL后,使用IL2CPP将他们从新变回C++代码,而后再由各个平台的C++编译器直接编译成能执行的原生汇编代码。
几点注意:
1.将IL变回CPP的目的除了CPP的执行效率快之外,另外一个很重要的缘由是能够利用现成的在各个平台的C++编译器对代码执行编译期优化,这样能够进一步减少最终游戏的尺寸并提升游戏运行速度。
2. 因为动态语言的特性,他们多半无需程序员太多关心内存管理,全部的内存分配和回收都由一个叫作GC(Garbage Collector)的组件完成。虽然经过IL2CPP之后代码变成了静态的C++,可是内存管理这块仍是遵循C#的方式,这也是为何最后还要有一个 IL2CPP VM的缘由:它负责提供诸如GC管理,线程建立这类的服务性工做。可是因为去除了IL加载和动态解析的工做,使得IL2CPP VM能够作的很小,而且使得游戏载入时间缩短。
3.因为C++是一门静态语言,这就意味着咱们不能使用动态语言的那些酷炫特性。运行时生 成代码并执行确定是不可能了。这就是Unity里面提到的所谓AOT(Ahead Of Time)编译而非JIT(Just In Time)编译。其实不少平台出于安全的考虑是不容许JIT的,你们最熟悉的有iOS平台,在Console游戏机上,无论是微软的Xbox360, XboxOne,仍是Sony的PS3,PS4,PSV,没有一个是容许JIT的。使用了IL2CPP,就彻底是AOT方式了,若是原来使用了动态特性的 代码确定会编译失败。这些代码在编译iOS平台的时候天生也会失败,因此若是你是为iOS开发的游戏代码,就不用担忧了。所以就这点而言,咱们开发上几乎 不会感到什么问题。
最后给出Unite 2014上官方给出的性能测试截图(数字越小表示运行得越快):浏览器
有了IL2CPP,程序尺寸能够相对缩小,运行速度能够提升!看了兴奋吗?其实现有的Unity版本中已经引入了IL2CPP技术。本文下篇就经过一个实际的例子,看看IL2CPP都为咱们作了哪些,以及咱们须要注意些什么。安全