[Unity]編譯順序與Script物件模型

Unity編譯程式碼時:
1. "Standard Assets"
以及 "Pro Standard Assets" 以及 "Plugins" 資料夾內的程式碼會優先編譯
2. "Standard Assets/Editor"
以及 "Pro Standard Assets/Editor" 以及 "Plugins/Editor" 會第二順位編譯
3.
所有不是放在 "Editor" 資料夾的程式碼第三順位編譯
4.
最後編譯所有放在 "Editor" 資料夾內的程式碼

 unity1.png

從這個類別圖我們可以理解它的結構,及如何把一些常用功能映射至這系統裡,以下分節討論。
GameObject Component
Unity 的執行環境裡,會有一個場境 (Scene)。這個場境包含一個 GameObject 物件的層階 (Hierarchy)
這個 GameObject 類別只是一個包容器,本身沒有其他功能。使用者需要為 GameObject 加入各種 Component 物件來定義它的行為,而不是透過繼承 (inherit) GameObject 來加入 行為。
一個物件可擁有多個 Component 物件,但有一些 Component 類別只可以在一個 GameObject 中有一個實體 (instance)
MonoBehavior
我最感興趣的,是使用者如何自行定義行為來做出不同的 Gameplay。在 Unity 中,程式員編寫的 Script,其實也是 Component 的一種,所有的 Script 都會繼承自 MonoBehavior 類別。以下是一個簡單例子:
var speed = 5.0;

function Update () {
    var x = Input.GetAxis("Horizontal") * Time.deltaTime * speed;
    var z = Input.GetAxis("Vertical") * Time.deltaTime * speed;
    transform.Translate(x, 0, z);
}
把這個 Script 加進一個 GameObject 的話 (成為該 GameObject 的一個 Component)Runtime 會在每幀呼叫 Update(),玩家就可以用上下左右鍵控制那個 GameObject 在水平方向移動。。
Transform
每個能在三維空間裡的 GameObject 都會有 Transform Component (未有詳細看是否有一些 GameObject 可以省郤 Transform,例如一個用來定義一個遊戲任務的 GameObject)Transform 包括位置、旋轉及縮放。
之前的例子已用了 transform component,不過它其實是 Object 類別的一個 shortcut,這 shortcut 其實等同:
GetComponent(Transform).Translate(x, 0, z)
Component 的連結
Script Tutorial 裡的例子是寫一個 Follow 的行為,擁有這個 Component GameObject 會自動追蹤 (面對著) 一個目標物件:
var target : Transform;

function Update () {
    transform.LookAt(target);
}
這個 Script 暴露了一個 target 變數 (應當作成員變數吧),使用者可以把其他物件的變數 assign 至這個變數。這 assignment 有兩種方法實現,其一是利用 Unity GUI 工具把一個 Component 實體的變數 (Transform) drag-and-drop 至這個 Component 實體的 target 變數,而另一個方法是寫代碼:
var newTarget = GameObject.Find("Cube").transform;
GetComponent(Follow).target = newTarget;
用代碼就可以這樣動態改變這些 Component 之間的聯結方式。或者另一個說法是,GUI 工具是可以設定起始的聯結,而 Script 可以在執行期改變這些聯結。
渲染
一個可被渲染的 GameObject 需要有以幾個 Components,以 Mesh 為例:
1.    MeshFilter: 用來找出現時的 Mesh 物件
2.    MeshRenderer: 用來渲染 Mesh Component,會參考一個 material 物件
要注要 Mesh Material 物件並非 Component,它們是繼承自 Object 的。但是你仍然可以去動態改變它們。但由於它們不是 Component ,所以可以被分享,例如多個 GameObject MeshRenderer 都參考到同一個 Material。一個 Component 實體只屬於一個 GameObject (所以在 UML 中我用黑色鑽石表示 Composition)
Light Camera 則是 Component,這意未著可以簡單的設定聯結。
分析
Unity Script 物件模型是以 Component 為基礎的。透過把 Component 實體加入 GameObject 實體來組合不同功能的物件,而 Component 實體之間可以建立聯結。
這種方式不需要透過繼承 (inheritance),而是透過聚合 (aggregation)加入物件的功能和行為。使用聚合的好處是不會產生複雜的繼承層階,亦可以動態改變聚合的結構 (例如在執行期加入或移除 Component)
有一些細節我暫時未清楚,例如多個 Component 在一個 GameObject 中的執行次序如何設定;聯結會否有 cylic 的問題等等。可能要拿到軟件再試用才可以知道。

參考資料:
1.解構UnityScript物件模型http://miloyip.seezone.net/?p=15
2.http://forum.mirax.com.tw/unity/viewtopic.php?f=134&t=1589


留言

這個網誌中的熱門文章

[Unity]UGUI 原理篇 (一):Canvas 渲染模式

[Android]JavaScript與Android溝通

[Android]加載圖片導致內存溢出(Out of Memory 異常)