Unity3D——C#编译到运行的过程分析
1、Unity引擎是如何做到跨平臺運行的
我們從基礎概念開始,一步步走進真相:
程序集
一個.Net程序由一個或者多個程序集組成,程序集可以是庫,也可以是應用程序。.Net中,庫項目導出的文件格式為.dll,應用程序導出后的文件格式為.exe。
類似Flash項目,也是由庫項目和應用程序項目組成。在Flash中,庫項目導出后的文件格式為.swc,應用程序導出后的文件格式為.swf。
比如:一般Unity項目里包含這四個C#庫項目:
vs編譯之后,然后我們在項目目錄的緩存目錄Library\ScriptAssemblies下,能找到對應的四個dll文件:
CIL(Common Language Runtime)
剛才我們提到C#庫項目導出之后生成的是一個DLL文件, 這個DLL文件里,存放的是CIL代碼集。
它是微軟在發布.Net框架的時候,一起發布的一個語言。CIL語言大概長這個樣子:
里面有幾個我們很熟悉的詞匯,Hello,world,System.Consolve::WriteLine。沒錯,它的功能就是輸出Hello,world。它原本的C#程序是這樣:
在.Net平臺下,所有的語言(C#,VB.NET等)都會被編譯成CIL,然后運行在虛擬機上,由虛擬機把CIL轉換成各個平臺的原生碼(CPU可直接執行的代碼)。
是不是又有點像Flash,Flash程序也是運行在虛擬機上的。
虛擬機——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跨平臺是如何做到跨平臺的:
1、把C#通過Mono compiler(其他語言用的是Unity單獨開發的一個Unity compiler),編譯成CIL語言;
2、各個平臺下的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的好處是:
1、運行速度快(CPP轉原生碼比CIL快);
2、減少Unity公司的維護成本:Mono VM官方是不支持那么多平臺的,所以很多平臺的Mono VM都需要Unity自己去制作和維護,而C++編譯器是本來各個平臺都現成的。
缺點是:
1、包體會變大;
2、編譯速度慢;3、不支持JIT。
2、Mono如何運行CIL
這個部分將會告訴大家,IOS平臺究竟有和特別之處,為什么在它上面實現代碼熱更新那么麻煩。
1、JIT(Just In Time)模式——在編譯的時候,把C#編譯成CIL,在運行時,逐條讀入,逐條解析翻譯成原生碼交給CPU再執行;
2、AOT(Ahead Of Time)模式——在編譯成CIL之后,會把CIL再處理一遍,編譯成原生碼,在運行的時候交給CPU直接執行,Mono下的AOT只會處理部分的CIL,還有一部分CIL采用了JIT的模式;
3、Full AOT模式——在編譯成CIL之后,把所有的CIL編譯成原生碼,在運行的時候直接執行。
(留個坑:AOT模式下,編譯出來的內容有兩部分:原生碼和CIL,它們是如何存放的,找了好多資料,沒查到,本地想測試,但是環境暫時搭不起來,這個后面和IL2CPP一起研究)
Windows和Android系統采用的是JIT模式,那IOS用的哪一種呢?
我們看到,JIT模式是邊運行,邊翻譯,支持運行時加載新的代碼進來。而IOS是禁止內存的可執行權限的,不允許在運行過程中創建新的函數等,所以必須要提前編譯好所有的代碼,更不用說在運行時加載新的代碼了。就是說,在IOS下,Mono采用的是Full AOT模式運行CIL。
轉載于:https://juejin.im/post/5b6a4bb36fb9a04fa671cebf
總結
以上是生活随笔為你收集整理的Unity3D——C#编译到运行的过程分析的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: Apache虚拟目录和多端口多主机名配置
- 下一篇: 【译】ES2018 新特性: 正则表达式
