- Unity 3D腳本編程:使用C#語言開發跨平臺游戲
- 陳嘉棟
- 1565字
- 2023-02-28 19:22:08
2.1 Mono是什么
Mono是一個由Xamarin公司所贊助的開源項目。它基于通用語言架構(Common Language Infrastructure,縮寫為CLI)和C#的ECMA標準(Ecma-334、Ecam-335),提供了微軟的.NET框架的另一種實現。與微軟的.NET框架不同的是,Mono具備了跨平臺的能力,也就是說它不僅能運行在Windows操作系統上,而且還可以運行在Mac OSX、Linux操作系統上,甚至是一些游戲平臺上。
自從2004年發布Mono 1.0版本以來,Mono也逐漸從Linux桌面應用程序開發者平臺發展成為了支持廣泛的硬件架構和操作系統的平臺。
而作為微軟的.NET框架在不同平臺上的重要補充,Mono也被很多公司所采用,這其中就包括Unity 3D的開發者——Unity Technologies公司。他們為Unity 3D引入了Mono,以幫助游戲開發者獲取開發跨平臺游戲的能力。
2.1.1 Mono的組成
從剖析Mono的組件來看看它是如何組成的。Mono的組件主要可以分為以下幾個部分。
? C#編譯器。目前最新的Mono版本(v4.0.1)的C#編譯器完全兼容C#1.0、2.0、3.0、4.0以及5.0。但是由于一些歷史原因,Unity 3D采用的Mono版本仍然停留在2.0+的階段。所以C#的一些新功能,在Unity 3D中是不會出現的。而在Mono的發展歷史上,同樣的編譯器卻有很多不同的版本。例如gmcs(編譯目標為2.0 mscorlib)、smcs(編譯目標為2.1 mscorlib,主要用來構建MoonLight應用)、dmcs(編譯目標為4.0 mscorlib)。而Mono從Mono 2.11版本開始,采用了一個統一的編譯器——mcs。它的出現替代了之前提到過的3種編譯器的不同版本。而由于mcs是C#寫的編譯器,而且還使用了很多.NET的API,所以在非Windows平臺上需要Mono運行時(Runtime)來運行mcs。而在Windows平臺上,既可以使用微軟的.NET運行時,也可以使用Mono運行時。
? Mono運行時。運行時實現了前面提到過的Ecma的通用語言架構標準,該標準是一個開放的技術規范,它定義了構成.NET框架基礎結構的可執行代碼,以及代碼的運行時環境,也就是說該標準旨在定義一個與具體語言無關的、跨架構系統的運行環境。具體而言,Mono運行時提供了一個即時編譯器(Just-in-time,縮寫為JIT),以及一個提前編譯器(Ahead-of-time compiler,縮寫為AOT)。同時還有類庫加載器、垃圾回收器和線程系統等。
? 基礎類庫。Mono平臺提供了廣泛的基礎類,為構建應用提供一個堅實的基礎,而這些類庫也同微軟的.NET框架兼容。
? Mono類庫。Mono也提供了很多超越基礎類庫、超越微軟的.NET框架的類。這些類提供了很多有用的額外功能,特別是在構建Linux的應用方面。例如一些處理Gtk+、Zip files、LDAP、OpenGL、Cairo、POSIX的類。
2.1.2 Mono運行時
在剛剛介紹的Mono組件中,提到了C#編譯器——mcs。而mcs的作用是將C#編譯為ECMA CIL的byte code,之后則需要Mono運行時中的編譯器,將CIL的byte code再轉譯為原生碼(Native Code,即本地CPV的圖標執行代碼)。Mono運行時為我們提供了2種編譯器和3種轉譯方式。3種轉譯方式如下。
? 即時編譯(Just-in-time,JIT):在程序運行的過程中,將CIL的byte code轉譯為目標平臺的原生碼。
? 提前編譯(Ahead-of-time,AOT):在程序運行之前,將.exe或.dll文件中的CIL的byte code轉譯為目標平臺的原生碼并且存儲起來。但仍會有一部分CIL的byte code會在程序運行的過程中進行轉譯,即有一部分轉譯工作仍需要JIT編譯。
? 完全靜態編譯(Full-ahead-of-time,Full-AOT):這種模式出現的目的,是完全杜絕在程序運行的過程中使用JIT編譯。也就是說在程序運行之前,所有的代碼已經被編譯成了目標平臺的原生碼。在Unity 3D開發中,最典型的平臺就是iOS平臺。
而Mono運行時提供的另一個重要的功能便是垃圾回收器(garbage collection,縮寫GC)。由于使用了垃圾回收機制,所以就避免了開發人員手動管理內存所帶來的風險,無須開發人員去告訴運行時環境究竟應該何時收回某個對象的空間,取而代之的是運行時會追蹤目標對象,并且自行決定是否回收對象的內存。不過與微軟.NET框架不同,在Mono 2.8版本發布的前后,它有兩套不同的垃圾回收機制——分代收集(generational collector)以及貝姆垃圾收集器(Boehm-Demers-Weiser garbage collector)。而Mono早期所采用的貝姆垃圾收集器與.NET框架的垃圾回收器相比一直有很大的限制,在某些狀況的應用軟件上會發生內存泄漏的現象,由于Unity 3D使用的并非微軟的.NET框架,而是開源的Mono,更具體地說是Mono比較早期的版本,所以Unity 3D的垃圾回收性能并不如.NET的垃圾回收性能。