前言編程
首先須要瞭解的是,Unity3D的C#基礎腳本模塊是經過Mono來實現的。c#
什麼是Mono?緩存
參考下百度百科:Mono是一個由Novell公司(由Xamarin發起)主持的項目,並由Miguel de lcaza領導的,一個致力於開創.NET在Linux上使用的開源工程。它包含了一個C#語言的編譯器,一個CLR的Runtime,和一組類庫,並實現了 ADO NET和ASP NET。spa
它基於CIL和C#的ECMA標準,提供了了微軟.Net FrameWork的另外一種實現。操作系統
Mono主要有如下部分組成:翻譯
C#編譯器——mcs。(最新的Mono版本已經能夠支持C#5.0,但Unity3D的Mono版本仍然停留在2.0+階段(支持c#3.0),因此C#的一些新功能沒法在unity中使用)接口
運行時:即時編譯器JIT(後文會介紹)。以及GC,類庫加載器等等。開發
基礎類庫(BCL)。get
Mono類庫。提供了超出微軟.NET的一些類,提供了許多額外功能,主要是用於構建其餘操做系統上的應用。編譯器
下面進入正題:
Mono和Unity
Unity引擎自己是由C++寫出的,只不過Mono被嵌入到了Unity當中,爲unity提供了一個完整的虛擬機運行環境。這樣Mono的嵌入接口會將Mono Runtime暴露給Unity底層的C++代碼。經過這些接口,開發者就能夠控制Mono Runtime,以及依託於Mono Runtime的託管代碼。
Unity爲什麼可以跨平臺?
一句話歸納,主要緣由在於Unity經過Mono使用了一種叫CIL(Common Intermediate Language,也叫MSIL)通用中間語言的基於堆棧的代碼指令集,它屬於CLR的一個子集。
Unity3D的開發過程當中,代碼的編譯主要分爲兩個過程:
1)首先將對應的腳本代碼編譯成CIL(以後CIL還會被編譯成一種位元碼,生成一個CLI集合)。
2)而後Mono在運行時將CLI集合中的位元碼編譯爲本地運行的原生指令。(這裏會使用到上文中的JIT、AOT編譯模式)
注:也就是說在Mono中運行的實際上是CIL,而在本地運行的是被編譯後生成的原生指令。
這裏再提一下什麼是JIT和AOT
JIT:即時編譯,或者又稱爲動態編譯,是在程序執行時才編譯代碼,即將一條中間託管語句(CLI)翻譯成一條機器語句,而後執行這條語句。但它同時也會將編譯過的代碼進行緩存,而不是每一次都進行編譯。因此說它是靜態編譯和解釋器的結合體。
AOT:靜態編譯,一樣使用了JIT來進行編譯,只不過它在程序運行以前就編譯好了。但仍是有一部分代碼會即時編譯。
AOT的過程簡要:
1)收集須要編譯的代碼。
2)使用JIT編譯代碼。
3)發射編譯過的代碼和一些元數據
4)調用本地彙編器或鏈接器處理後生成可執行文件。
注:IOS平臺禁止使用JIT編譯器,因此Mono提供了一種FULL AOT模式,這裏不贅述。
總結
Unity的跨平臺,就是經過Mono將C#腳本代碼編譯成CLI,而後Mono運行時利用JIT或者AOT將CLI編譯成目標平臺的原生代碼實現的。
參考資料
1.百度百科
https://baike.baidu.com/item/CIL/3583850?fr=aladdin
https://baike.baidu.com/item/JIT%E7%BC%96%E8%AF%91%E5%99%A8/3793585
2.電子工業出版社:《Unity3D腳本編程》 做者:陳嘉棟