原型链是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的更多相关文章

  1. 用ECMAScript4 ( ActionScript3) 实现Unity的热更新

    unity热更新是一个经久不衰的话题.除了最常见的lua之外,还有如JSBinding,C#等等.这里介绍一个使用ECMAScript4进行热更新的方案.它吸收了各家的优点,特色很鲜明. 项目地址: ...

  2. 用ECMAScript4 ( ActionScript3) 实现Unity的热更新 -- Demo分析

    如何创建工程 下载最新的Unity发布插件包. 打开Unity,新建一个项目 将插件包导入 在菜单中点击ASRuntime/Create ActionScript3 FlashDevelop HotF ...

  3. 用ECMAScript4 ( ActionScript3) 实现Unity的热更新 -- 使用第三方组件

    Unity开发中,常常会用到一些第三方组件.本文以实例介绍如何在热更新脚本中使用这些第三方组件. 首先说明几个基本步骤: 第三方组件通常是以dll或者源码方式提供的,它们本身往往无法热更. 我们在脚本 ...

  4. 用ECMAScript4 ( ActionScript3) 实现Unity的热更新 -- CustomYieldInstruction 自定义中断指令

    ActionScript3脚本引擎为了方便热更新逻辑开发,提供的从脚本继承Unity类库功能在一些情况下可以提供开发的便利. 这次来建立一个示例,演示一下如何在脚本中自定义协程中断指令 Unity中的 ...

  5. 用ECMAScript4 ( ActionScript3) 实现Unity的热更新 -- 使用FairyGUI (一)

    我们的热更新脚本在实际使用中,当然也要支持常用的第三方组件,例如这里介绍一个非常实用的第三方UI库:FairyGUI. 什么是FairyGUI 这里照搬FaiyGUI官网的介绍: 重新定义 UI 制作 ...

  6. 用ECMAScript4 ( ActionScript3) 实现Unity的热更新 -- 使用FairyGUI (二)

    上次讲解了FairyGUI的最简单的热更新办法,并对其中一个Demo进行了修改并做成了热更新的方式. 这次我们来一个更加复杂一些的情况:Emoji. FairyGUI的   Example 04 - ...

  7. 用ECMAScript4 ( ActionScript3) 实现Unity的热更新 -- 热更新Live2D

    live2D是一个很强大的2D动画组件.我们可以使用AS3脚本对它进行热更新. live2D在Unity中的使用请看这里: 如何获取Live2D 总得来说,我们可以先去live2D官网下载它的Unit ...

  8. 用ECMAScript4 ( ActionScript3) 实现Unity的热更新 -- 在脚本中使用MonoBehaviour

    继上次分析了热更新的Demo后,这次来介绍如何在热更新代码中使用MonoBehaviour. MonoBehaviour挂载到GameObject对象上的脚本的基类.平常Unity开发时,简单的做法就 ...

  9. 用ECMAScript4 ( ActionScript3) 实现Unity的热更新 -- 操作符重载和隐式类型转换

    C#中,某些类型会定义隐式类型转换和操作符重载.Unity中,有些对象也定义了隐式类型转换和操作符重载.典型情况有:UnityEngine.Object.UnityEngine.Object的销毁是调 ...

随机推荐

  1. 使用属性升级MyBank

    一.访问修饰符  private   :使用private访问修饰符修饰的属性或者方法只能在本类中使用 public    :可以在任何类中访问到 二.this 关键字:代表当前类,this.属性:代 ...

  2. selenium2自动化测试学习笔记(三)

    今天是学习selenium的第三天,今天的主题是自动登录126邮箱. 今天总结碰到的坑有三个: 1.frame内元素抓取,使用driver.switch_to.frame(frameId)方法切换锁定 ...

  3. 网络工具nslookup的使用

    根据域名查询ip 如下所示: bogon:~ hhh$ nslookup www.baidu.com. Server: 192.168.1.254. #默认的DNS服务器 Address: . #ip ...

  4. Semaphore 源码分析

    Semaphore 源码分析 1. 在阅读源码时做了大量的注释,并且做了一些测试分析源码内的执行流程,由于博客篇幅有限,并且代码阅读起来没有 IDE 方便,所以在 github 上提供JDK1.8 的 ...

  5. Alpha冲刺——Day2

    一.合照 二.项目燃尽图 三.项目进展 图形界面基本完成 接口文档框架完成,接下来将会不断细化填充 登录界面向服务器请求数据进行ing 四.明日规划 1.注册登录接口能够完成 2.研究idea实现获得 ...

  6. 安装iis8

    -------------------- @echo off     echo 正在添加IIS8.0 功能,依据不同的网络速率,全程大约需要5分钟时间...     start /w pkgmgr / ...

  7. The sum of numbers form 0 to n.(20.9.2017)

    #include <stdio.h> int main() { int a,b,sum; printf("输入一个数字: "); scanf("%d" ...

  8. 《高级软件测试》JIRA使用手册(一)JIRA基本情况

    JIRA 官方网站为:https://www.atlassian.com/software/jira 中文代理网站为:https://www.jira.cn 现版本:v7.3.0 Atlassian公 ...

  9. 常用的 html 标签及注意事项

    <a> 标签 用法:用于定义超链接 清除浏览器默认样式: a { text-decoration: none;/* 去除下划线 */ color: #333;/* 改变链接颜色 */ } ...

  10. JAVA_SE基础——37.main方法的详解

    主函数 大家都会写吧. 大家一直都不知道为何这样设计,这样设计有什么好处呢? 白话解释: main函数的修饰符是public: 公共的 为何不用private 等等的修饰符 而规定只用public呢? ...