標籤:blog assembly value getc target class game eve type
原型鏈是JS的必備,作為ECMAScript4,原型鏈也是支援的。
特別說明,ActionScript3是支援完整的物件導向繼承支援的,原型鏈只在某些非常特殊的情況下使用。
本文旨在介紹如何使用原型鏈。
任意物件類型都有一個prototype屬性,包括匯入的Unity的API也有。我們可以和JS一樣的對這個prototype進行操作,比如動態新增成員,添加方法等。
- 如果您決定使用原型鏈,那麼必須捨棄編譯時間類型檢查。如果使用強型別,則編譯器會認為動態添加的成員不存在,而提示編譯錯誤。解決辦法為去掉變數的類型說明,或者將變數強制轉換成Object。
- 和JS引擎一樣,原型鏈必須在運行時順著prototype鏈尋找。因此會影響效能。
本文說明,如何在指令碼中,動態監聽 EventTrigger。我們將這篇文章中介紹的使用不可熱更的C#代碼做的監聽,改寫為ActionScript3實現。
工程說明
- 建立一個Untiy工程,並且建立AS3熱更新項目。如果不會建立,請參考這裡
- 在HotFixDemoScene1上添加一個Image。
- 本次代碼需要使用 RectTransformUtility 這個類。如果是Unity2017.2版本以後,由於這個類型被分拆到了其他dll (UnityEngine.UIModule.dll),因此需要將它加入到配置表裡。
- 開啟熱更新工程的genapi.config.xml ,將如下配置加入配置節中:
<!--Configure DLLs to export--> <buildassemblys> <assembly value="D:\Program Files\Unity\Editor\Data\Mono\lib\mono\2.0\System.dll"></assembly> <assembly value="D:\Program Files\Unity\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.dll"></assembly> <assembly value="D:\Program Files\Unity\Editor\Data\Managed\UnityEngine\UnityEngine.UIModule.dll"></assembly> <assembly value="D:\Program Files\Unity\Editor\Data\UnityExtensions\Unity\GUISystem\UnityEngine.UI.dll"></assembly> <assembly value="F:/ASTool_UnityTest/HotFix_EventTrigger\Library\ScriptAssemblies\Assembly-CSharp.dll"></assembly> </buildassemblys>
- 開啟熱更新項目的Main.as檔案,將內容改為如下代碼:
package{ [Doc] /** * ... * @author */ public class Main { public function Main() { } public function update():void { } } }import as3runtime.RefOutStore;import system.collections.generic.List_Of_EventTrigger_Entry;import unityengine.GameObject;import unityengine.MonoBehaviour;import unityengine.RectTransform;import unityengine.RectTransformUtility;import unityengine.Vector3;import unityengine.events.UnityAction_Of_BaseEventData;import unityengine.eventsystems.BaseEventData;import unityengine.eventsystems.EventTrigger;import unityengine.eventsystems.EventTriggerType;import unityengine.eventsystems.EventTrigger_Entry;import unityengine.eventsystems.PointerEventData;class UGUIEventTriggerTool{ /** * 靜態方法。檢查某個GameObject上是否包含EventTrigger組件。如果有則返回它,否則建立一個並返回。 * @param go 輸入的GameObject * @return 返回EventTrigger */ public static function Get(go:GameObject):EventTrigger { var trigger:EventTrigger = go.getComponent(EventTrigger) as EventTrigger; if (null == trigger) { trigger = EventTrigger(go.addComponent(EventTrigger)); } return trigger; } }/* * * 在EventTrigger的原型鏈上定義AddEventListener方法。 * EventTrigger類型沒有公開建構函式,因此API匯出時,不會為他建立在指令碼中繼承的介面。 * 這裡我們可以用原型鏈來對它進行擴充。 * 包外代碼只會執行一次。所以只會在原型鏈上定義一次AddEventListener方法。 * */EventTrigger.prototype.AddEventListener = function (eventTriggerType:EventTriggerType, action:UnityAction_Of_BaseEventData):void { /** * EventTrigger有一個嵌套內部類 UnityEngine.EventSystems.EventTrigger.Entry。 * 由於ActionScript3並不支援嵌套類,因此它被匯出成為EventTrigger_Entry。 */ var entry:EventTrigger_Entry = new EventTrigger_Entry(); entry.eventID = eventTriggerType; entry.callback.addListener(action); this.triggers.add(entry); } /** * 擴充MonoBehaviour,讓Image組件可以被拖拽。 */class UGUIEventTriggerTest extends MonoBehaviour{ function Start() { /** * 此處使用 * 類型來代表任意類型。 * 這樣即可跳過編譯時間類型檢查,使用原型鏈。 * 否則將會提示編譯錯誤。 */ var t:* = UGUIEventTriggerTool.Get(gameObject); /** * 調用在原型鏈上定義的方法,給Drag事件添加處理函數。 * 我們可以直接使用匿名函數來作為處理函數。 */ t.AddEventListener(EventTriggerType.Drag, function (baseData:BaseEventData):void { var data:PointerEventData = baseData as PointerEventData; var rt:RectTransform = data.pointerPress.getComponent(RectTransform) as RectTransform; var globalMousePos:Vector3; /** * RectTransformUtility.screenPointToWorldPointInRectangle的參數 * worldPoint : (Out)UnityEngine.Vector3 * 是一個Ref Out參數。ActionScript3是沒有ref和out關鍵字的, * 因此這裡使用RefOutStore來接收返回的參數。 */ var store:RefOutStore = new RefOutStore(); if (RectTransformUtility.screenPointToWorldPointInRectangle(rt, data.position, data.pressEventCamera, globalMousePos,store)) { //傳入形參名,來提取值。 globalMousePos = store.getValue("worldPoint") as Vector3; rt.position = globalMousePos; } } ); } }//將指令碼掛載到Image上。GameObject.find("Image").addComponent(UGUIEventTriggerTest);
- 點擊編譯,然後在Unity中點擊播放。我們現在即可拖動這個Image。
用ECMAScript4 ( ActionScript3) 實現Unity的熱更新 -- 使用原型鏈和EventTrigger