【干貨】Mono和IL2CPP的區別
我們都知道游戲必須是跨平臺的。我們不能只支持一個平臺。否則,如果每個對應的平臺都做了相應的編譯器,那就真的很累人了。所以跨平臺的需求,對于游戲開發來說,是非常重要的。當然Unity也需要這個特性。
Unity是如何實現跨平臺的?
這就介紹了mono和il2cpp,這兩種在unity中編寫后端腳本的方法。讓我們弄清楚兩者之間的區別。
一、Mono
Wiki:Mono是一個由Xamarin公司(先前是Novell,最早為Ximian)所主持的自由開放源碼項目。該項目的目標是創建一系列符合ECMA標準的.NET工具,包括C#編譯器和通用語言架構。與微軟的.NET Framework不同,Mono項目不僅可以運行于Windows系統上,還可以運行于Linux、Unix、OS X,甚至一些游戲平臺。
Mono組成組件:C# 編譯器,CLI虛擬機,以及核心類別程序庫。
工作流程:
-
通過C#編譯器mcs,將C#編譯為IL(中間語言,byte code)
-
通過Mono運行時中的編譯器將IL編譯成對應平臺的原生碼
IL科普
IL的全稱是 Intermediate Language,很多時候還會看到CIL(Common Intermediate Language,特指在.Net平臺下的IL標準)。翻譯過來就是中間語言。
它是一種屬于通用語言架構和.NET框架的低階(lowest-level)的人類可讀的編程語言。目標為.NET框架的語言被編譯成CIL,然后匯編成字節碼。
CIL類似一個面向對象的匯編語言,并且它是完全基于堆棧的,它運行在虛擬機上(.Net Framework, Mono VM)的語言。
具體過程是:C#或者VB這樣遵循CLI規范的高級語言,被先被各自的編譯器編譯成中間語言:IL(CIL),等到需要真正執行的時候,這些IL會被加載到運行時庫,也就是VM中,由VM動態的編譯成匯編代碼(JIT)然后在執行。
知識點:
1.1. 編譯器
C#編譯器mcs:將C#編譯為IL
Mono運行時中的編譯器:將IL轉移為原生碼。
1.2. 三種轉譯方式:
(1)即時編譯(Just-in-time,JIT):程序運行過程中,將CIL的byte code轉譯為目標平臺的原生碼。
(2) 提前編譯(Ahead-of-time,AOT):程序運行之前,將.exe或.dll文件中的CIL的byte code部分轉譯為目標平臺的原生碼并且存儲,程序運行中仍有部分CIL的byte code需要JIT編譯。
(3)完全靜態編譯(Full-ahead-of-time,Full-AOT):程序運行前,將所有源碼編譯成目標平臺的原生碼。
1.3 Unity跨平臺的原理
Mono運行時編譯器支持將IL代碼轉為對應平臺原生碼,IL可以在任何支持CLI(Common Language Insfrastructure,通用語言環境結構)中運行,IL的運行是依托于Mono運行時。
1.3 Unity跨平臺的原理
Mono運行時編譯器支持將IL代碼轉為對應平臺原生碼,IL可以在任何支持CLI(Common Language Insfrastructure,通用語言環境結構)中運行,IL的運行是依托于Mono運行時。
1.4 IOS不支持jit編譯原因:
機器碼被禁止映射到內存,即封存了內存的可執行權限,變相的封鎖了jit編譯方式。
1.5 JIT編譯
將IL代碼轉為對應平臺原生碼并且將原生碼映射到虛擬內存中執行。JIT編譯的時候IL是在依托Mono運行時,轉為對應的原生碼后在依托本地運行。
優點:
-
構建應用非常快
-
由于Mono的JIT(Just In Time compilation ) 機制, 所以支持更多托管類庫
-
支持運行時代碼執行
-
必須將代碼發布成托管程序集(.dll 文件 , 由mono或者.net 生成 )
-
Mono VM在各個平臺移植異常麻煩,有幾個平臺就得移植幾個VM(WebGL和UWP這兩個平臺只支持 IL2CPP)
-
Mono版本授權受限,C#很多新特性無法使用
-
iOS仍然支持Mono , 但是不再允許Mono(32位)應用提交到Apple Store
unity 2018 mono版本仍然是mono2.0、unity2020的版本更新到了mono 5.11。
二、IL2CPP【AOT編譯】
- 通過AOT編譯器把IL中間語言轉換成CPP文件。
- 運行時庫提供服務和抽象,例如垃圾收集器,與平臺和線程和文件的獨立訪問以及內部調用的實現(直接修改托管數據結構的本機代碼)。
2.1 AOT編譯器
IL2CPP AOT編譯器名為il2cpp.exe。在Windows上,您可以在Editor \ Data \ il2cpp目錄中找到它。在OSX上,它位于Unity安裝的Contents / Frameworks / il2cpp / build目錄中。il2cpp.exe實用程序是一個托管可執行文件,完全用C#編寫。
IL2CPP工具鏈:
2.2 運行時庫
IL2CPP技術的另一部分是運行時庫,用于支持虛擬機。
我們將運行時庫稱為libil2cpp,這個簡單且可移植的運行時庫是IL2CPP技術的主要優勢之一
通過查看我們隨Unity一起提供的libil2cpp的頭文件,您可以找到有關libil2cpp代碼組織方式的一些線索(您可以在Windows的Editor \ Data \ PlaybackEngines \ webglsupport \ BuildTools \ Libraries \ libil2cpp \ include目錄中找到它們) ,或OSX上的Contents / Frameworks / il2cpp / libil2cpp目錄)。
2.3 為啥要轉成CPP呢?
快!!!
根據官方的實驗數據,換成IL2CPP以后,程序的運行效率有了1.5-2.0倍的提升。
2. Mono VM在各個平臺移植,維護非常耗時,有時甚至不可能完成
Mono的跨平臺是通過Mono VM實現的,有幾個平臺,就要實現幾個VM,像Unity這樣支持多平臺的引擎,Mono官方的VM肯定是不能滿足需求的。所以針對不同的新平 臺,Unity的項目組就要把VM給移植一遍,同時解決VM里面發現的bug。這非常耗時耗力。這些能移植的平臺還好說,還有比如WebGL這樣基于瀏覽 器的平臺。要讓WebGL支持Mono的VM幾乎是不可能的。
3. 可以利用現成的在各個平臺的C 編譯器對代碼執行編譯期優化,這樣可以進一步減小最終游戲的尺寸并提高游戲運行速度。
4. 由于動態語言的特性,他們多半無需程序員太多關心內存管理,所有的內存分配和回收都由一個叫做GC(Garbage Collector)的組件完成。雖然通過IL2CPP以后代碼變成了靜態的C ,但是內存管理這塊還是遵循C#的方式,這也是為什么最后還要有一個 IL2CPP VM的原因:它負責提供諸如GC管理,線程創建這類的服務性工作。但是由于去除了IL加載和動態解析的工作,使得IL2CPP VM可以做的很小,并且使得游戲載入時間縮短。
2.4 編譯區別
使用Mono的時候,腳本的編譯運行如下圖所示:
3大腳本被編譯成IL,在游戲運行的時候,IL和項目里其他第三方兼容的DLL一起,放入Mono VM虛擬機,由虛擬機解析成機器碼,并且執行IL2CPP做的改變由下圖紅色部分標明:
在得到中間語言IL后,使用IL2CPP將他們重新變回C 代碼,然后再由各個平臺的C 編譯器直接編譯成能執行的原生匯編代碼。
優點
-
相比Mono, 代碼生成有很大的提高
-
可以調試生成的C 代碼
-
可以啟用引擎代碼剝離(Engine code stripping)來減少代碼的大小
-
程序的運行效率比Mono高,運行速度快
-
多平臺移植非常方便
-
相比Mono構建應用慢
-
只支持AOT(Ahead of Time)編譯
三、區別
IL2CPP比較適合開發和發布項目 ,但是為了提高版本迭代速度,可以在開發期間切換到Mono模式(構建應用快)。
轉載聲明:本文來源于網絡,不作任何商業用途

全部評論


暫無留言,趕緊搶占沙發
熱門資訊

來自韓國3d建模師 yeonghee cho 的《魅魔succubus》,...

第18屆王座杯CG大賽獲獎名單公布!

繪學霸規則玩法大全

CGWANG王氏教育怎么樣?

天賦與努力并存的漫畫家loundraw作品欣賞

王座杯人氣獎投票即將開始!請準備好你寶貴的1票~...

【游戲設計】游戲美術場景設計步驟

游戲《雙人成行》總監:我下一款作品更牛逼...

《糖豆人終極淘汰賽》「絆愛」服裝限時銷售,你會入手嗎?...
