用ECMAScript4 ( ActionScript3) 实现Unity的热更新 -- 使用原型链和EventTrigger
原型链是JS的必备,作为ECMAScript4,原型链也是支持的。
特别说明,ActionScript3是支持完整的面向对象继承支持的,原型链只在某些非常特殊的情况下使用。
本文旨在介绍如何使用原型链。
任意对象类型都有一个prototype属性,包括导入的Unity的API也有。我们可以和JS一样的对这个prototype进行操作,比如动态的添加成员,添加方法等。
- 如果您决定使用原型链,那么必须舍弃编译时类型检查。如果使用强类型,则编译器会认为动态添加的成员不存在,而提示编译错误。解决办法为去掉变量的类型说明,或者将变量强制转换成Object。
- 和JS引擎一样,原型链必须在运行时顺着prototype链查找。因此会影响性能。
本文说明,如何在脚本中,动态监听 EventTrigger。我们将这篇文章中介绍的使用不可热更的C#代码做的监听,改写为ActionScript3实现。
工程说明
- 新建一个Untiy工程,并且创建AS3热更新项目。如果不会创建,请参考这里
- 在HotFixDemoScene1上添加一个Image。
- 本次代码需要使用 RectTransformUtility 这个类。如果是Unity2017.2版本以后,由于这个类型被分拆到了其他dll (UnityEngine.UIModule.dll),因此需要将它加入到配置表里。
- 打开热更新工程的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> - 打开热更新项目的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); - 点击编译,然后在Unity中点击播放。我们现在即可拖动这个Image。
用ECMAScript4 ( ActionScript3) 实现Unity的热更新 -- 使用原型链和EventTrigger的更多相关文章
- 用ECMAScript4 ( ActionScript3) 实现Unity的热更新
unity热更新是一个经久不衰的话题.除了最常见的lua之外,还有如JSBinding,C#等等.这里介绍一个使用ECMAScript4进行热更新的方案.它吸收了各家的优点,特色很鲜明. 项目地址: ...
- 用ECMAScript4 ( ActionScript3) 实现Unity的热更新 -- Demo分析
如何创建工程 下载最新的Unity发布插件包. 打开Unity,新建一个项目 将插件包导入 在菜单中点击ASRuntime/Create ActionScript3 FlashDevelop HotF ...
- 用ECMAScript4 ( ActionScript3) 实现Unity的热更新 -- 使用第三方组件
Unity开发中,常常会用到一些第三方组件.本文以实例介绍如何在热更新脚本中使用这些第三方组件. 首先说明几个基本步骤: 第三方组件通常是以dll或者源码方式提供的,它们本身往往无法热更. 我们在脚本 ...
- 用ECMAScript4 ( ActionScript3) 实现Unity的热更新 -- CustomYieldInstruction 自定义中断指令
ActionScript3脚本引擎为了方便热更新逻辑开发,提供的从脚本继承Unity类库功能在一些情况下可以提供开发的便利. 这次来建立一个示例,演示一下如何在脚本中自定义协程中断指令 Unity中的 ...
- 用ECMAScript4 ( ActionScript3) 实现Unity的热更新 -- 使用FairyGUI (一)
我们的热更新脚本在实际使用中,当然也要支持常用的第三方组件,例如这里介绍一个非常实用的第三方UI库:FairyGUI. 什么是FairyGUI 这里照搬FaiyGUI官网的介绍: 重新定义 UI 制作 ...
- 用ECMAScript4 ( ActionScript3) 实现Unity的热更新 -- 使用FairyGUI (二)
上次讲解了FairyGUI的最简单的热更新办法,并对其中一个Demo进行了修改并做成了热更新的方式. 这次我们来一个更加复杂一些的情况:Emoji. FairyGUI的 Example 04 - ...
- 用ECMAScript4 ( ActionScript3) 实现Unity的热更新 -- 热更新Live2D
live2D是一个很强大的2D动画组件.我们可以使用AS3脚本对它进行热更新. live2D在Unity中的使用请看这里: 如何获取Live2D 总得来说,我们可以先去live2D官网下载它的Unit ...
- 用ECMAScript4 ( ActionScript3) 实现Unity的热更新 -- 在脚本中使用MonoBehaviour
继上次分析了热更新的Demo后,这次来介绍如何在热更新代码中使用MonoBehaviour. MonoBehaviour挂载到GameObject对象上的脚本的基类.平常Unity开发时,简单的做法就 ...
- 用ECMAScript4 ( ActionScript3) 实现Unity的热更新 -- 操作符重载和隐式类型转换
C#中,某些类型会定义隐式类型转换和操作符重载.Unity中,有些对象也定义了隐式类型转换和操作符重载.典型情况有:UnityEngine.Object.UnityEngine.Object的销毁是调 ...
随机推荐
- vue 2.0之基础
Vue Vue实例 创建实例: var vm = new Vue({ //code }) 数据与方法: 只有当实例被创建时 data 中存在的属性才是响应式的; Vm.b = 'h1' 是不会触发视图 ...
- ECEF和大地坐标系的相互转化
在阅读 RTKLIB的源码时,发现了ECEF和大地坐标系的相互转换的函数,大地坐标系(φ,λ,h)转成ECEF(X,Y,Z)与所看书籍(GPS原理与接收机,谢刚,电子工业出版社)的公式是一样的,而EC ...
- 剑指Offer-二叉树的下一个结点
题目描述 给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回.注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针. 思路 分析二叉树的下一个节点,一共有以下情况: 二叉树 ...
- 移动端H5地图矢量SHP网格切分打包方案
文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.背景 与离线瓦片方案一样,同样是为了解决移动端网速和流量问题,但是却 ...
- 【RabbitMQ系列】 Spring mvc整合RabbitMQ
一.linux下安装rabbitmq 1.安装erlang环境 wget http://erlang.org/download/otp_src_18.2.1.tar.gz tar xvfz otp_s ...
- 用C语言实现QQ刷屏
我在百度传课上录制了一个用C语言实现刷屏的视频,有兴趣的可以移步这边:https://chuanke.baidu.com/6658388-238008.html
- 项目Alpha冲刺Day2
一.会议照片 二.项目进展 1.今日安排 初步搭建后台框架,根据昨天的最终设计再修改原型,成功使用powerDesigner导出sql. 2.问题困难 使用了比较多的框架,而且是首次尝试纯java配置 ...
- 201421123042 《Java程序设计》第13周学习总结
1. 本周学习总结 以你喜欢的方式(思维导图.OneNote或其他)归纳总结多网络相关内容. 答: 2. 为你的系统增加网络功能(购物车.图书馆管理.斗地主等)-分组完成 为了让你的系统可以被多个用户 ...
- 2017 清北济南考前刷题Day 4 afternoon
期望得分:30+50+30=110 实际得分:40+0+0=40 并查集合并再次写炸... 模拟更相减损术的过程 更相减损术,差一定比被减数小,当被减数=减数时,停止 对于同一个减数来说,会被减 第1 ...
- django + nginx + uwsgi + websocket
最近使用django框架做了一个简单的聊天机器人demo, 开发的过程中使用了django自带的websocket模块,当使用django框架自带的wsgi服务去启动的话,没有什么问题.如果要使用uw ...