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

來源:互聯網
上載者:User

標籤:blog   assembly   value   getc   target   class   game   eve   type   

原型鏈是JS的必備,作為ECMAScript4,原型鏈也是支援的。

特別說明,ActionScript3是支援完整的物件導向繼承支援的,原型鏈只在某些非常特殊的情況下使用。

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

任意物件類型都有一個prototype屬性,包括匯入的Unity的API也有。我們可以和JS一樣的對這個prototype進行操作,比如動態新增成員,添加方法等。

  1. 如果您決定使用原型鏈,那麼必須捨棄編譯時間類型檢查。如果使用強型別,則編譯器會認為動態添加的成員不存在,而提示編譯錯誤。解決辦法為去掉變數的類型說明,或者將變數強制轉換成Object。
  2. 和JS引擎一樣,原型鏈必須在運行時順著prototype鏈尋找。因此會影響效能。

本文說明,如何在指令碼中,動態監聽 EventTrigger。我們將這篇文章中介紹的使用不可熱更的C#代碼做的監聽,改寫為ActionScript3實現。

工程說明
  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。


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

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.