咱們從基礎概念開始,一步步走進真相:緩存
一個.Net程序由一個或者多個程序集組成,程序集能夠是庫,也能夠是應用程序。.Net中,庫項目導出的文件格式爲.dll,應用程序導出後的文件格式爲.exe。框架
相似Flash項目,也是由庫項目和應用程序項目組成。在Flash中,庫項目導出後的文件格式爲.swc,應用程序導出後的文件格式爲.swf。函數
好比:通常Unity項目裏包含這四個C#庫項目:測試
vs編譯以後,而後咱們在項目目錄的緩存目錄Library\ScriptAssemblies下,能找到對應的四個dll文件:翻譯
剛纔咱們提到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
你們在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
剛纔咱們已經知道了Unity跨平臺是如何作到跨平臺的:
一、把C#經過Mono compiler(其餘語言用的是Unity單獨開發的一個Unity compiler),編譯成CIL語言;
二、各個平臺下的Mono虛擬機,運行CIL語言,轉換成原生碼給CPU執行。
其實Unity後來出了另一個方案:IL2PP。
它會在項目轉成CIL以後,再把CIL轉成CCPP,而後在運行的時候,把CPP加載進來,由各個平臺的IL2PP VM轉換成原生碼。
Mono模式下編譯出來的安卓包體:
\assets\bin\Data\Managed\ Assembly-CSharp.dll 爲遊戲的控制邏輯,運行時調用。 \lib\armeabi-v7a\IL2CPP模式下編譯出來的安卓包體:
\assets\bin\Data\Managed\ 已經沒有了DLL文件。 \lib\armeabi-v7a\ libmono.so變成了libil2cpp.so,包含了Mono模式下的DLL和IL2CPP VM功能一、運行速度快(CPP轉原生碼比CIL快);
二、減小Unity公司的維護成本:Mono VM官方是不支持那麼多平臺的,因此不少平臺的Mono VM都須要Unity本身去製做和維護,而C++編譯器是原本各個平臺都現成的。
一、包體會變大;
二、編譯速度慢;三、不支持JIT。
這個部分將會告訴你們,IOS平臺究竟有和特別之處,爲何在它上面實現代碼熱更新那麼麻煩。
(留個坑:AOT模式下,編譯出來的內容有兩部分:原生碼和CIL,它們是如何存放的,找了好多資料,沒查到,本地想測試,可是環境暫時搭不起來,這個後面和IL2CPP一塊兒研究)
Windows和Android系統採用的是JIT模式,那IOS用的哪種呢?
咱們看到,JIT模式是邊運行,邊翻譯,支持運行時加載新的代碼進來。而IOS是禁止內存的可執行權限的,不容許在運行過程當中建立新的函數等,因此必需要提早編譯好全部的代碼,更不用說在運行時加載新的代碼了。就是說,在IOS下,Mono採用的是Full AOT模式運行CIL。