用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。

相关文章
相关标签/搜索