zoukankan      html  css  js  c++  java
  • 用ECMAScript4 ( ActionScript3) 实现Unity的热更新 -- 使用原型链和EventTrigger

    原型链是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 FilesUnityEditorDataMonolibmono2.0System.dll"></assembly>
          <assembly value="D:Program FilesUnityEditorDataManagedUnityEngineUnityEngine.CoreModule.dll"></assembly>
          <assembly value="D:Program FilesUnityEditorDataManagedUnityEngineUnityEngine.UIModule.dll"></assembly>
          <assembly value="D:Program FilesUnityEditorDataUnityExtensionsUnityGUISystemUnityEngine.UI.dll"></assembly>
          
          <assembly value="F:/ASTool_UnityTest/HotFix_EventTriggerLibraryScriptAssembliesAssembly-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。


  • 相关阅读:
    matlab mex中C++内存全局共享和持久化
    算法导论01---到底何为算法(由算法联想到的大学教育)
    在Visual Studio项目中根据系统平台自动引用32或64位的DLL
    POJ2352【树状数组】
    artDialog双击会关闭对话框的修改
    利用AWR 查看SQL 执行计划
    Sql获取数据集中各类型中的最大值(最新值)
    容器常用操作
    运行容器的最佳实践
    两种进入容器的方法
  • 原文地址:https://www.cnblogs.com/ashei/p/8885175.html
Copyright © 2011-2022 走看看