NGUI 3.0 之后 采用了 一种 全新的 事件系统 List<EventDelegate> ,使用起来并不麻烦。
但是最近做项目碰到一个小问题,特此分享一下。
PS NGUI3.6.4版本
PS 有空还是看看 源码,有些 时候 光理解 还是没用的。
一、问题出现在UI 逻辑一块,在一个 UITween 调用之后 要回调一个 事件。
代码如下:
1 public class MyTest2 : MonoBehaviour 2 { 3 public UITweener tween; 4 5 6 List<EventDelegate> list; 7 public virtual void Start () { 8 list = tween.onFinished; 9 10 EventDelegate.Add(tween.onFinished, Test); 11 } 12 13 List<string> list1 = new List<string>(); 14 void Test() 15 { 16 Debug.Log(list == tween.onFinished); 17 18 EventDelegate.Remove(tween.onFinished, Test); 19 20 Debug.Log(" Test "); 21 } 22 23 void OnGUI() 24 { 25 if (GUI.Button(new Rect(10, 10, 150, 100), "I am a button")) 26 tween.PlayForward(); 27 if (GUI.Button(new Rect(10, 110, 150, 100), "I am a button2")) 28 tween.PlayReverse(); 29 } 30 31 32 }
但是之前 我是 以为 EventDelegate.Remove 这样就能够把 Onfinished 委托给去除的。
结果我发现不是如此,之后 这个 Tween 每次 调用 结束 之后, Test() 都会执行。
二、源码分析
看了下源码。发现问题出在这里:
这段代码就是 tween 结束后 调用的。
来观察一下 EventDelegate 的 流程
我们可以看到 他 使用了 onFinished 的 list , add 了 一个 包含了 test() Callback 的 EventDelegate
接下里 执行结束的的时候 使用了 同样的 list ,编辑得到 刚才那个 包含了 test() Callback 的 EventDelegate ,然后执行其中的 test()
同样的 Remove 操作也是如此。
但是 我们可以看到 tween 结束后 onFinished 已经 变过了。
所以这样一来 , EventDelegate.Remove 使用的 list 不再是 原来那个list,
也就意味着 tween 结束后 会永远调用 test() ,因为我们没有用 原来的 list 来 Remove 包含了 test() Callback 的 EventDelegate .
三、解决方法
但是我感觉 治标 不 治本,如果 我 想 调用 好几次 再 Remove 呢 ? 以后有空 在弄吧。
1 public class MyTest2 : MonoBehaviour 2 { 3 public UITweener tween; 4 5 6 List<EventDelegate> list; 7 public virtual void Start () { 8 list = tween.onFinished; 9 10 //EventDelegate.Add(tween.onFinished, Test); 11 EventDelegate.Add(tween.onFinished, Test, true); 12 } 13 14 List<string> list1 = new List<string>(); 15 void Test() 16 { 17 Debug.Log(list == tween.onFinished); 18 19 //EventDelegate.Remove(tween.onFinished, Test); 20 21 Debug.Log(" Test "); 22 } 23 24 void OnGUI() 25 { 26 if (GUI.Button(new Rect(10, 10, 150, 100), "PlayForward")) 27 { 28 Debug.Log(" PlayForward"); 29 tween.PlayForward(); 30 } 31 32 if (GUI.Button(new Rect(10, 110, 150, 100), "PlayReverse")) 33 { 34 Debug.Log(" PlayReverse "); 35 tween.PlayReverse(); 36 } 37 38 } 39 }
上结果:
时间: 2024-10-22 20:11:11