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> 小坑的更多相关文章

  1. mciSendString 的两个小坑

    刚刚修正了自己用的小闹钟的代码. 坑1:REPEAT 选项的作用范围 原来用得好好的,之后选择 .wav 文件,居然不出声音了…… 诶,MCI 肯定支持 .wav 的啊…… 仔细想想,我以前都是选 . ...

  2. 注意Android里TextView控件的一个小坑,用android:theme来设置样式时动态载入的layout会丢失该样式

    注意Android里TextView控件的一个小坑,用android:theme来设置样式时动态载入的layout会丢失该样式 这个坑,必须要注意呀, 比如在用ListView的时候,如果在List_ ...

  3. C#中的Infinity有个小坑

    (此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 昨天家里有事,上网也不方便,就没有推送文章.今天很累,也不长篇大论了.简单介绍一下最近遇到的 ...

  4. 使用EMMET中的小坑

    使用EMMET写HTML的时候,是一个非常爽的事情.但是今天我使用时,发现一个小坑.以前倒也没有注意,不过需要非常的小心. form[action="/process" metho ...

  5. 关于CSS3中transform变换的小坑

    2017年6月30日15:05:46 今天在写一个demo的时候,发现CSS3中transform变换的一个特性. 首先,我先描述一下我发现的情况(问题再现): <div class=" ...

  6. Vue中应用CORS实现AJAX跨域,及它在 form data 和 request payload 的小坑处理

    基本概念部分(一):理解CORS 说道Vue的跨域AJAX,我想先梳理一遍CORS跨域,"跨域资源共享"(Cross-origin resource sharing),它是一个W3 ...

  7. go的变量redeclare的问题,golang的一个小坑

    go的变量声明有几种方式: 1 通过关键字 var 进行声明 例如:var i int   然后进行赋值操作 i = 5 2 最简单的,通过符号 := 进行声明和赋值 例如: i:=5 golang会 ...

  8. MySQL中字段类型为timestamp的小坑

    之前遇到过一个MySQL的字段为timestamp类型的小坑. MySQL中一个字段存储时间类型数据的时候,该字段的类型如果为timestamp类型的话,最多只能存储到2038-01-19 11:14 ...

  9. mysql url 连接配置的一个小坑。 工作中不会遇到。 学习的时候会

    <property name="driverClassName"> <value>com.mysql.jdbc.Driver</value> & ...

随机推荐

  1. Linux下动态共享库加载及使用详解【转】

    原文地址:http://blog.chinaunix.net/uid-29025972-id-3855500.html 对动态库的实际应用还不太熟悉的读者可能曾经遇到过类似“error while l ...

  2. 去掉影响效率的where 1=1

    最近看了篇文章,觉得挺有道理.实际项目中,我们进行sql条件过滤,我们不能确定是不是有条件.也不能确定条件的个数.大多数人会先把sql语句组装为: 这样,如果有其他过滤条件直接加上“and 其他条件” ...

  3. Codevs 1105 过河

     时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond  题目描述 Description 在河上有一座独木桥,一只青蛙想沿着独木桥从河的一侧跳到另一侧.在桥上有 ...

  4. Codevs 1231 最优布线问题

    题目描述 Description 学校需要将n台计算机连接起来,不同的2台计算机之间的连接费用可能是不同的.为了节省费用,我们考虑采用间接数据传输结束,就是一台计算机可以间接地通过其他计算机实现和另外 ...

  5. 弹性布局-flex

    浅谈display:flex   display:flex 意思是弹性布局 首先flex的出现是为了解决哪些问题呢? 一.页面行排列布局 像此图左右两个div一排显示 可以用浮动的布局方式 html部 ...

  6. Linux--变量与虚拟内存

    定义一个变量:存储类型  数据类型  变量名 存储类型(变量存储的位置):auto.register.static.extern 1.auto:对于局部变量,atuo可以缺省.位置:栈 2.exter ...

  7. 33选6算法:M个数N个为一组,无重复的排列组合

    private void button1_Click(object sender, EventArgs e) { int nCnt = 0; List nNumList = new List(); f ...

  8. Java生成唯一GUID UUID

    GUID(Global unique identifier)全局唯一标识符,它是由网卡上的标识数字(每个网卡都有唯一的标识号)以及 CPU 时钟的唯一数字生成的的一个 16 字节的二进制值. GUID ...

  9. 基于Python的密码生成程序的优化

    近期刚刚组织完内部的Python基础培训.GUI的开发培训,之后布置的作业是两人一组,利用前面所写的一些模块做一些小软件. 具体就是模拟Advanced Password Generator这个软件的 ...

  10. Java中的继承和多态

    1.  什么是继承,继承的特点? 子类继承父类的特征和行为,使得子类具有父类的各种属性和方法.或子类从父类继承方法,使得子类具有父类相同的行为. 特点:在继承关系中,父类更通用.子类更具体.父类具有更 ...