Unity3D——C#編譯到運行的過程分析

一、Unity引擎是如何作到跨平臺運行的

咱們從基礎概念開始,一步步走進真相:緩存

程序集

一個.Net程序由一個或者多個程序集組成,程序集能夠是庫,也能夠是應用程序。.Net中,庫項目導出的文件格式爲.dll,應用程序導出後的文件格式爲.exe。框架

相似Flash項目,也是由庫項目和應用程序項目組成。在Flash中,庫項目導出後的文件格式爲.swc,應用程序導出後的文件格式爲.swf。函數

好比:通常Unity項目裏包含這四個C#庫項目:測試

vs編譯以後,而後咱們在項目目錄的緩存目錄Library\ScriptAssemblies下,能找到對應的四個dll文件:翻譯

CIL(Common Language Runtime)

剛纔咱們提到C#庫項目導出以後生成的是一個DLL文件, 這個DLL文件裏,存放的是CIL代碼集。3d

它是微軟在發佈.Net框架的時候,一塊兒發佈的一個語言。CIL語言大概長這個樣子:cdn

裏面有幾個咱們很熟悉的詞彙,Hello,world,System.Consolve::WriteLine。沒錯,它的功能就是輸出Hello,world。

它本來的C#程序是這樣:blog

在.Net平臺下,全部的語言(C#,VB.NET等)都會被編譯成CIL,而後運行在虛擬機上,由虛擬機把CIL轉換成各個平臺的原生碼(CPU可直接執行的代碼)。遊戲

是否是又有點像Flash,Flash程序也是運行在虛擬機上的。ip

虛擬機——Mono

你們在Unity項目中都見過Mono這個詞,MonoDeveloper,MonoBehavior等,那Mono究竟是個什麼東西?

Mono是一個基於CLR的開源項目,容許引擎和用戶的託管代碼運行在每個目標平臺上。而CLR全稱爲通用語言運行平臺(Common Language Runtime),是微軟的.Net虛擬機。它其中兩個主要做用是:1,編譯——運行前把C#編譯爲CIL;2,運行——在運行的時把CIL轉換成各平臺的原生碼。

這些是Mono支持的平臺:Android,Apple iOS(iOS,Apple macOS,Apple tvOS,Apple watchOS),BSD (OpenBSD, FreeBSD, NetBSD),Linux,Microsoft Windows,Nintendo Wii,Sony PlayStation 3,Sony PlayStation 4,Sun Solaris

IL2CPP

剛纔咱們已經知道了Unity跨平臺是如何作到跨平臺的:

一、把C#經過Mono compiler(其餘語言用的是Unity單獨開發的一個Unity compiler),編譯成CIL語言;

二、各個平臺下的Mono虛擬機,運行CIL語言,轉換成原生碼給CPU執行。

其實Unity後來出了另一個方案:IL2PP。

它會在項目轉成CIL以後,再把CIL轉成CCPP,而後在運行的時候,把CPP加載進來,由各個平臺的IL2PP VM轉換成原生碼。

Mono vs IL2CPP

Mono模式下編譯出來的安卓包體:

\assets\bin\Data\Managed\

Assembly-CSharp.dll 爲遊戲的控制邏輯,運行時調用。

\lib\armeabi-v7a\
libmono.so包含了mono VM的功能

IL2CPP模式下編譯出來的安卓包體:

\assets\bin\Data\Managed\

已經沒有了DLL文件。 \lib\armeabi-v7a\

libmono.so變成了libil2cpp.so,包含了Mono模式下的DLL和IL2CPP VM功能

IL2CPP的好處是:

一、運行速度快(CPP轉原生碼比CIL快);

二、減小Unity公司的維護成本:Mono VM官方是不支持那麼多平臺的,因此不少平臺的Mono VM都須要Unity本身去製做和維護,而C++編譯器是原本各個平臺都現成的。

缺點是:

一、包體會變大;

二、編譯速度慢;

三、不支持JIT。

二、Mono如何運行CIL

這個部分將會告訴你們,IOS平臺究竟有和特別之處,爲何在它上面實現代碼熱更新那麼麻煩。

一、JIT(Just In Time)模式——在編譯的時候,把C#編譯成CIL,在運行時,逐條讀入,逐條解析翻譯成原生碼交給CPU再執行;

二、AOT(Ahead Of Time)模式——在編譯成CIL以後,會把CIL再處理一遍,編譯成原生碼,在運行的時候交給CPU直接執行,Mono下的AOT只會處理部分的CIL,還有一部分CIL採用了JIT的模式;

三、Full AOT模式——在編譯成CIL以後,把全部的CIL編譯成原生碼,在運行的時候直接執行。

(留個坑:AOT模式下,編譯出來的內容有兩部分:原生碼和CIL,它們是如何存放的,找了好多資料,沒查到,本地想測試,可是環境暫時搭不起來,這個後面和IL2CPP一塊兒研究)

Windows和Android系統採用的是JIT模式,那IOS用的哪種呢?

咱們看到,JIT模式是邊運行,邊翻譯,支持運行時加載新的代碼進來。而IOS是禁止內存的可執行權限的,不容許在運行過程當中建立新的函數等,因此必需要提早編譯好全部的代碼,更不用說在運行時加載新的代碼了。就是說,在IOS下,Mono採用的是Full AOT模式運行CIL。

相關文章
相關標籤/搜索