NGUI List 小坑


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 結束后 調用的。

這里把 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() 就沒有了。

 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 }

 

上結果:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM