用ECMAScript4 ( ActionScript3) 實現Unity的熱更新 -- 使用原型鏈和EventTrigger

原型鏈是JS的必備,做爲ECMAScript4,原型鏈也是支持的。html

特別說明,ActionScript3是支持完整的面向對象繼承支持的,原型鏈只在某些很是特殊的狀況下使用。api

本文旨在介紹如何使用原型鏈。函數

任意對象類型都有一個prototype屬性,包括導入的Unity的API也有。咱們能夠和JS同樣的對這個prototype進行操做,好比動態的添加成員,添加方法等。性能

  1. 若是您決定使用原型鏈,那麼必須捨棄編譯時類型檢查。若是使用強類型,則編譯器會認爲動態添加的成員不存在,而提示編譯錯誤。解決辦法爲去掉變量的類型說明,或者將變量強制轉換成Object。
  2. 和JS引擎同樣,原型鏈必須在運行時順着prototype鏈查找。所以會影響性能。

本文說明,如何在腳本中,動態監聽 EventTrigger。咱們將這篇文章中介紹的使用不可熱更的C#代碼作的監聽,改寫爲ActionScript3實現。ui

工程說明

  1. 新建一個Untiy工程,而且建立AS3熱更新項目。若是不會建立,請參考這裏
  2. 在HotFixDemoScene1上添加一個Image。
  3. 本次代碼須要使用 RectTransformUtility 這個類。若是是Unity2017.2版本之後,因爲這個類型被分拆到了其餘dll (UnityEngine.UIModule.dll),所以須要將它加入到配置表裏。
  4. 打開熱更新工程的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>
  5. 打開熱更新項目的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);
  6. 點擊編譯,而後在Unity中點擊播放。咱們如今便可拖動這個Image。

相關文章
相關標籤/搜索