【转】Unity3D将来时:IL2CPP(上)
生活随笔
收集整理的這篇文章主要介紹了
【转】Unity3D将来时:IL2CPP(上)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Unity3D想必大家都不陌生,獨立游戲制作者們很多人都在用它,甚至一些大公司也用在很商業的游戲制作上。Unity3D最大的一個特點是一次制作,多平臺部署,而這一核心功能是靠Mono實現的。可以說Mono是Unity3D核心的核心,是Unity3D跨平臺的根本。但是在2014年年中的時候,Unity3D官方博客上卻發了一篇“The future of scripting in unity”的文章,引出了IL2CPP的概念,感覺有取代Mono之勢。那什么是IL2CPP,它能為Unity3D和作為使用Unity3D的我們帶來哪些好處和改變?這就是本文嘗試說明的。
C#,.Net Framework
微軟公司已經向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#或者VB這樣遵循CLI規范的高級語言,被先被各自的編譯器編譯成中間語言:IL(CIL),等到需要真正執行的時候,這些IL會被加載到運行時庫,也就是VM中,由VM動態的編譯成匯編代碼(JIT)然后在執行。
正是由于引入了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.提高運行效率 使用Mono的時候,腳本的編譯運行如下圖所示: 使用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開發的游戲代碼,就不用擔心了。因此就這點而言,我們開發上幾乎不會感到什么問題。 有了IL2CPP,程序尺寸可以相對縮小,運行速度可以提高!看了興奮嗎?其實現有的Unity版本中已經引入了IL2CPP技術。本文下篇就通過一個實際的例子,看看IL2CPP都為我們做了哪些,以及我們需要注意些什么。
http://zh.wikipedia.org/wiki/C%E2%99%AF
http://zh.wikipedia.org/wiki/%E5%AE%89%E5%BE%B7%E6%96%AF%C2%B7%E6%B5%B7%E5%B0%94%E6%96%AF%E4%BC%AF%E6%A0%BC
http://zh.wikipedia.org/wiki/Mono
http://zh.wikipedia.org/wiki/.NET%E6%A1%86%E6%9E%B6
總結
以上是生活随笔為你收集整理的【转】Unity3D将来时:IL2CPP(上)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【转】U3D手游《苍穹变》性能优化经验谈
- 下一篇: 【转】c#中类的默认访问修饰符