前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >用ECMAScript4 ( ActionScript3) 实现Unity的热更新 -- 使用原型链和EventTrigger

用ECMAScript4 ( ActionScript3) 实现Unity的热更新 -- 使用原型链和EventTrigger

作者头像
用户1687945
发布2018-05-02 11:38:31
1.2K0
发布2018-05-02 11:38:31
举报

原型链是JS的必备,作为ECMAScript4,原型链也是支持的。

特别说明,ActionScript3是支持完整的面向对象继承支持的,原型链只在某些非常特殊的情况下使用。

本文旨在介绍如何使用原型链。

任意对象类型都有一个prototype属性,包括导入的Unity的API也有。我们可以和JS一样的对这个prototype进行操作,比如动态的添加成员,添加方法等。

  1. 如果您决定使用原型链,那么必须舍弃编译时类型检查。如果使用强类型,则编译器会认为动态添加的成员不存在,而提示编译错误。解决办法为去掉变量的类型说明,或者将变量强制转换成Object。
  2. 和JS引擎一样,原型链必须在运行时顺着prototype链查找。因此会影响性能。

本文说明,如何在脚本中,动态监听 EventTrigger。我们将这篇文章中介绍的使用不可热更的C#代码做的监听,改写为ActionScript3实现。

工程说明

  1. 新建一个Untiy工程,并且创建AS3热更新项目。如果不会创建,请参考这里
  2. 在HotFixDemoScene1上添加一个Image。
  1. 本次代码需要使用 RectTransformUtility 这个类。如果是Unity2017.2版本以后,由于这个类型被分拆到了其他dll (UnityEngine.UIModule.dll),因此需要将它加入到配置表里。
  2. 打开热更新工程的genapi.config.xml ,将如下配置加入配置节中:
代码语言:javascript
复制
<!--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>
  1. 打开热更新项目的Main.as文件,将内容改为如下代码:
代码语言:javascript
复制
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);
  1. 点击编译,然后在Unity中点击播放。我们现在即可拖动这个Image。
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-04-20 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 工程说明
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档