NGUI List<EventDelegate> 小坑
NGUI 3.0 之后 采用了 一种 全新的 事件系统 List<EventDelegate> ,使用起来并不麻烦。
但是最近做项目碰到一个小问题,特此分享一下。
PS NGUI3.6.4版本
PS 有空还是看看 源码,有些 时候 光理解 还是没用的。
一、问题出现在UI 逻辑一块,在一个 UITween 调用之后 要回调一个 事件。
代码如下:
public class MyTest2 : MonoBehaviour
{
public UITweener tween; List<EventDelegate> list;
public virtual void Start () {
list = tween.onFinished; EventDelegate.Add(tween.onFinished, Test);
} List<string> list1 = new List<string>();
void Test()
{
Debug.Log(list == tween.onFinished); EventDelegate.Remove(tween.onFinished, Test); Debug.Log(" Test ");
} void OnGUI()
{
if (GUI.Button(new Rect(, , , ), "I am a button"))
tween.PlayForward();
if (GUI.Button(new Rect(, , , ), "I am a button2"))
tween.PlayReverse();
} }
但是之前 我是 以为 EventDelegate.Remove 这样就能够把 Onfinished 委托给去除的。
结果我发现不是如此,之后 这个 Tween 每次 调用 结束 之后, Test() 都会执行。

二、源码分析
看了下源码。发现问题出在这里:
这段代码就是 tween 结束后 调用的。
这里把 mTemp = OnFinish
再把 原来的OnFinish 指向了 一个 新 的 new 的 list
然后在 mTemp execute 执行完毕 之后 ,再旧瓶装新酒,把mTemp重新装进 OnFinish 这个list.

来观察一下 Add 的 流程
我们可以看到 他 使用了 onFinished 的 list , add 了 一个 包含了 test() Callback 的 EventDelegate

接下里 执行 的的时候 使用了 同样的 list ,编辑得到 刚才那个 包含了 test() Callback 的 EventDelegate ,然后执行其中的 test()

同样的 Remove 操作也是如此。

但是 我们可以看到 tween Execute 的 时候 调用 原来 增加进来的 Test 函数,
可是在 Test 函数 中 这个时候引用 的 onFinished 已经 变过了。成为了一个新的 new list.并且还没有把 原来的 委托放进来。
所以这样一来 , 即使你调用 EventDelegate.Remove , 因为 onFinished list.cout == 0 , 没有 remove test()
也就意味着 tween 结束后 会永远调用 test() 。因为在 tween Execute 之后,onFinish 这个 list 才会加入 原来 所有的 委托,这个时候 list.cout 才是1. 重新 加入了 test() 这个时候 remove 才有意义。

三、解决方法
但是我感觉 治标 不 治本,如果 我 想 调用 好几次 再 Remove 呢 ? 以后有空 在弄吧。
其实就是 在 执行的 时候 判断 一下,oneShot 标志位,执行完毕后mTemp 中 remove test(),再放到OnFisish 的时候 test() 就没有了。
public class MyTest2 : MonoBehaviour
{
public UITweener tween; List<EventDelegate> list;
public virtual void Start () {
list = tween.onFinished; //EventDelegate.Add(tween.onFinished, Test);
EventDelegate.Add(tween.onFinished, Test, true);
} List<string> list1 = new List<string>();
void Test()
{
Debug.Log(list == tween.onFinished); //EventDelegate.Remove(tween.onFinished, Test); Debug.Log(" Test ");
} void OnGUI()
{
if (GUI.Button(new Rect(, , , ), "PlayForward"))
{
Debug.Log(" PlayForward");
tween.PlayForward();
} if (GUI.Button(new Rect(, , , ), "PlayReverse"))
{
Debug.Log(" PlayReverse ");
tween.PlayReverse();
} }
}
上结果:

NGUI List<EventDelegate> 小坑的更多相关文章
- mciSendString 的两个小坑
刚刚修正了自己用的小闹钟的代码. 坑1:REPEAT 选项的作用范围 原来用得好好的,之后选择 .wav 文件,居然不出声音了…… 诶,MCI 肯定支持 .wav 的啊…… 仔细想想,我以前都是选 . ...
- 注意Android里TextView控件的一个小坑,用android:theme来设置样式时动态载入的layout会丢失该样式
注意Android里TextView控件的一个小坑,用android:theme来设置样式时动态载入的layout会丢失该样式 这个坑,必须要注意呀, 比如在用ListView的时候,如果在List_ ...
- C#中的Infinity有个小坑
(此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 昨天家里有事,上网也不方便,就没有推送文章.今天很累,也不长篇大论了.简单介绍一下最近遇到的 ...
- 使用EMMET中的小坑
使用EMMET写HTML的时候,是一个非常爽的事情.但是今天我使用时,发现一个小坑.以前倒也没有注意,不过需要非常的小心. form[action="/process" metho ...
- 关于CSS3中transform变换的小坑
2017年6月30日15:05:46 今天在写一个demo的时候,发现CSS3中transform变换的一个特性. 首先,我先描述一下我发现的情况(问题再现): <div class=" ...
- Vue中应用CORS实现AJAX跨域,及它在 form data 和 request payload 的小坑处理
基本概念部分(一):理解CORS 说道Vue的跨域AJAX,我想先梳理一遍CORS跨域,"跨域资源共享"(Cross-origin resource sharing),它是一个W3 ...
- go的变量redeclare的问题,golang的一个小坑
go的变量声明有几种方式: 1 通过关键字 var 进行声明 例如:var i int 然后进行赋值操作 i = 5 2 最简单的,通过符号 := 进行声明和赋值 例如: i:=5 golang会 ...
- MySQL中字段类型为timestamp的小坑
之前遇到过一个MySQL的字段为timestamp类型的小坑. MySQL中一个字段存储时间类型数据的时候,该字段的类型如果为timestamp类型的话,最多只能存储到2038-01-19 11:14 ...
- mysql url 连接配置的一个小坑。 工作中不会遇到。 学习的时候会
<property name="driverClassName"> <value>com.mysql.jdbc.Driver</value> & ...
随机推荐
- 学习笔记:JavaScript传参方式———ECMAScript中所有函数的参数都是按值传递
我们把命名参数(arguments)视为局部变量,在向参数传递基本类型值时,如同基本类型变量的复制一样,传递一个副本,参数在函数内部的改变不会影响外部的基本类型值.如: function add10( ...
- PCB参数计算神器-Saturn PCB Design Toolkit下载及安装指南
进行PCB设计,特别是高频高速设计时,难免会涉及到PCB相关参数的计算及设置,如:VIA的过流能力,VIA的寄生电容.阻抗等,导线的载流能力,两相互耦合信号线间的串扰,波长等参数. 这里向大家介绍一款 ...
- 将json转为复杂url参数
//json转url参数 var parseParam = function(param, key) { var paramStr = ""; if (param instance ...
- Nginx+Center OS 7.2 开机启动设置(转载)
centos 7以上是用Systemd进行系统初始化的,Systemd 是 Linux 系统中最新的初始化系统(init),它主要的设计目标是克服 sysvinit 固有的缺点,提高系统的启动速度.关 ...
- 一个统计目录文件大小的php函数
早上刚到公司,头告诉我,抓紧写一个小函数,用来统计指定目录中文件大小,我了个去,动手吧,还好有点小基础,一会就完工了,哈哈.代码在下面咯. <? /** 统计目录文件大小的函数 @author ...
- 分享:mysql 随机查询数据
在mysql中查询5条不重复的数据,使用以下: 1 SELECT * FROM `table` ORDER BY RAND() LIMIT 5 就可以了.但是真正测试一下才发现这样效率非常低.一个1 ...
- jquery鼠标滑过提示title具体实现代码
jquery鼠标滑过提示title的实现代码. 如下: <script type="text/javascript" src="http://ajax.google ...
- iis 下的 selfssl
当然,如果你想省掉所有这些麻烦也行,最简单的在IIS启动SSL的方法只要3步: 1. 下载 IIS 6.0 Resource Kit Tools: http://www.microsoft.com/d ...
- 自定义一个WPF的PathButton
一.背景 做项目时总是少不了Button,但是普通的Button大家都不喜欢用,总是想要自定义的Button,正好项目中用到不要边框的Button,并且是形状也是根据功能不同而变化的,并且窗口程序是会 ...
- 我应该直接学Swift还是Objective-C?
当我们发布了Swift语言学习课程之后,收到了很多邮件和私信来问自己是否还需要学习C或者Objective-C.此外,人们似乎还在迷惑Swift到底适合iOS开发生态中的哪些部分.通过这篇文章,我希望 ...