Tasharen Entertainment Forum

Support => NGUI 3 Support => Topic started by: you_inoue on October 15, 2014, 03:40:39 AM

Title: EventDelegate.Execute()
Post by: you_inoue on October 15, 2014, 03:40:39 AM
Hi!
I am using NGUI3.6.8.

Run the code below.
"OnFinish2" is called at the time of "OnFinish1."

  1. [RequireComponent(typeof(UIPlayTween))]
  2. public class PlayTweenTest : MonoBehaviour
  3. {
  4.         UIPlayTween pt;
  5.         void Start()
  6.         {
  7.                 if (pt == null)
  8.                         pt = GetComponent<UIPlayTween>();
  9.                 TweenPosition.Begin(gameObject, 5f, new Vector3(1f, 0f, 0f));
  10.                 EventDelegate.Add(pt.onFinished, OnFinish1, true);
  11.                 pt.Play(true);
  12.         }
  13.         void OnFinish1()
  14.         {
  15.                 Debug.Log("OnFinish1");
  16.                 EventDelegate.Add(pt.onFinished, OnFinish2, true);
  17.                 pt.Play(false);
  18.         }
  19.         void OnFinish2()
  20.         {
  21.                 Debug.Log("OnFinish2");
  22.         }
  23. }
  24.  

The cause is "EventDelegate.Execute" of for statement.
for statement running, list change, It is not to operate as expected.
I was changed to a secure code.

There was a problem.
"UITweener.duration = 0".
"OnFinish2" is not called.

It was troubled. :'(

  1. EventDelegate.Execute
  2. ----------------------------------------------------------------------
  3. [NGUI3.6.8]
  4. for (int i = 0; i < list.Count; )
  5. {
  6.         EventDelegate del = list[i];
  7.  
  8.         if (del != null)
  9.         {
  10.                 del.Execute();
  11.  
  12.                 if (i >= list.Count) break;
  13.                 if (list[i] != del) continue;
  14.  
  15.                 if (del.oneShot)
  16.                 {
  17.                         list.RemoveAt(i);
  18.                         continue;
  19.                 }
  20.         }
  21.         ++i;
  22. }
  23. ----------------------------------------------------------------------
  24. [Change]
  25. foreach (var del in list.ToArray())
  26. {
  27.         if (del != null)
  28.         {
  29.                 del.Execute();
  30.                 if (del.oneShot)
  31.                         list.Remove(del);
  32.         }
  33. }
  34. ----------------------------------------------------------------------
  35.  
Title: Re: EventDelegate.Execute()
Post by: ArenMook on October 16, 2014, 05:56:08 AM
First Play(), then add/set a delegate. Don't set it first.
Title: Re: EventDelegate.Execute()
Post by: you_inoue on October 16, 2014, 06:38:42 AM
This?
  1. [RequireComponent(typeof(UIPlayTween))]
  2. public class PlayTweenTest : MonoBehaviour
  3. {
  4.     UIPlayTween pt;
  5.     void Start()
  6.     {
  7.         if (pt == null)
  8.             pt = GetComponent<UIPlayTween>();
  9.         TweenPosition.Begin(gameObject, 5f, new Vector3(1f, 0f, 0f));
  10.         pt.Play(true); // first
  11.         EventDelegate.Add(pt.onFinished, OnFinish1, true); // second
  12.     }
  13.     void OnFinish1()
  14.     {
  15.         Debug.Log("OnFinish1");
  16.         pt.Play(false); // first
  17.         EventDelegate.Add(pt.onFinished, OnFinish2, true); // second
  18.     }
  19.     void OnFinish2()
  20.     {
  21.         Debug.Log("OnFinish2");
  22.     }
  23. }
  24.  
There was a problem.
"Play()" and "add/set", It performs with a different frame?
Title: Re: EventDelegate.Execute()
Post by: ArenMook on October 16, 2014, 07:02:01 AM
Different frame? What do you mean?

As long as you have a non-duration delay, it'll work as expected.

If your duration is zero then don't bother using a tween at all.
Title: Re: EventDelegate.Execute()
Post by: you_inoue on October 16, 2014, 07:51:07 AM
Different frame? What do you mean?

As long as you have a non-duration delay, it'll work as expected.

If your duration is zero then don't bother using a tween at all.

Update NGUI3.7.4.
There was a problem.
duration = 5.0f
 :'( :'(

  1. // Same frame
  2. IEnumerator SameFrame()
  3. {
  4.     pt.Play(true);
  5.     EventDelegate.Add(pt.onFinished, OnFinish1, true);
  6.     yield return null;
  7. }
  8. // Different frame
  9. IEnumerator DifferentFrame()
  10. {
  11.     pt.Play(true);
  12.     yield return null;
  13.     EventDelegate.Add(pt.onFinished, OnFinish1, true);
  14. }
  15.  
Title: Re: EventDelegate.Execute()
Post by: ArenMook on October 17, 2014, 04:32:13 AM
Change EventDelegate.Add to EventDelegate.Set.
Title: Re: EventDelegate.Execute()
Post by: you_inoue on October 19, 2014, 10:58:22 PM
The problem is not settled.
Besides, there is not OneShot.
"OnFinish2" two times are called.
Title: Re: EventDelegate.Execute()
Post by: ArenMook on October 20, 2014, 11:17:41 PM
If you use Set instead of Add, previous callback will be removed. You won't get it called twice. I suggest you look closer at your code to see where you're adding it twice.
Title: Re: EventDelegate.Execute()
Post by: you_inoue on October 21, 2014, 12:39:58 AM
This is.

  1. // PlayTweenTest.cs
  2.  
  3. using UnityEngine;
  4. using System.Collections;
  5.  
  6. [RequireComponent(typeof(UIPlayTween))]
  7. public class PlayTweenTest : MonoBehaviour
  8. {
  9.         UIPlayTween pt;
  10.         void Start()
  11.         {
  12.                 if (pt == null)
  13.                         pt = GetComponent<UIPlayTween>();
  14.                 TweenPosition.Begin(gameObject, 5f, new Vector3(1f, 0f, 0f));
  15.                 EventDelegate.Set(pt.onFinished, OnFinish1); // before Add
  16.                 pt.Play(true);
  17.         }
  18.         void OnFinish1()
  19.         {
  20.                 Debug.Log("OnFinish1");
  21.                 EventDelegate.Set(pt.onFinished, OnFinish2); // before Add
  22.                 pt.Play(false);
  23.         }
  24.         void OnFinish2()
  25.         {
  26.                 Debug.Log("OnFinish2");
  27.         }
  28. }
  29.  

1.New Scene.
2.Create GameObject.
3.GameObject AddComponent PlayTweenTest.cs
4.Scene Play.

It is possible to confirm it.

Now NGUI3.7.4.
Title: Re: EventDelegate.Execute()
Post by: ArenMook on October 22, 2014, 04:20:02 AM
You are basically modifying UIPlayTween's event list while executing the same list. UITweener was written to account for this happening, but UIPlayTween was not.

This script doesn't use UIPlayTween and works as expected:
  1. using UnityEngine;
  2. using System.Collections;
  3.  
  4. public class Test : MonoBehaviour
  5. {
  6.         void OnClick ()
  7.         {
  8.                 UITweener tw = GetComponent<UITweener>();
  9.                 tw.Play(true);
  10.                 EventDelegate.Add(tw.onFinished, OnFinish1, true);
  11.         }
  12.  
  13.         public void OnFinish1 ()
  14.         {
  15.                 Debug.Log("OnFinish1");
  16.                 UITweener tw = GetComponent<UITweener>();
  17.                 tw.Play(false);
  18.                 EventDelegate.Add(tw.onFinished, OnFinish2, true);
  19.         }
  20.  
  21.         public void OnFinish2 ()
  22.         {
  23.                 Debug.Log("OnFinish2");
  24.         }
  25. }
  26.  
Title: Re: EventDelegate.Execute()
Post by: you_inoue on October 23, 2014, 11:02:21 PM
Can not be used in UIPlayTween. :'(
OK!
Thank you! :) :)