Author Topic: EventDelegate.Execute()  (Read 7397 times)

you_inoue

  • Newbie
  • *
  • Thank You
  • -Given: 2
  • -Receive: 0
  • Posts: 15
    • View Profile
EventDelegate.Execute()
« 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.  

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: EventDelegate.Execute()
« Reply #1 on: October 16, 2014, 05:56:08 AM »
First Play(), then add/set a delegate. Don't set it first.

you_inoue

  • Newbie
  • *
  • Thank You
  • -Given: 2
  • -Receive: 0
  • Posts: 15
    • View Profile
Re: EventDelegate.Execute()
« Reply #2 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?

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: EventDelegate.Execute()
« Reply #3 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.

you_inoue

  • Newbie
  • *
  • Thank You
  • -Given: 2
  • -Receive: 0
  • Posts: 15
    • View Profile
Re: EventDelegate.Execute()
« Reply #4 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.  

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: EventDelegate.Execute()
« Reply #5 on: October 17, 2014, 04:32:13 AM »
Change EventDelegate.Add to EventDelegate.Set.

you_inoue

  • Newbie
  • *
  • Thank You
  • -Given: 2
  • -Receive: 0
  • Posts: 15
    • View Profile
Re: EventDelegate.Execute()
« Reply #6 on: October 19, 2014, 10:58:22 PM »
The problem is not settled.
Besides, there is not OneShot.
"OnFinish2" two times are called.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: EventDelegate.Execute()
« Reply #7 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.

you_inoue

  • Newbie
  • *
  • Thank You
  • -Given: 2
  • -Receive: 0
  • Posts: 15
    • View Profile
Re: EventDelegate.Execute()
« Reply #8 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.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: EventDelegate.Execute()
« Reply #9 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.  

you_inoue

  • Newbie
  • *
  • Thank You
  • -Given: 2
  • -Receive: 0
  • Posts: 15
    • View Profile
Re: EventDelegate.Execute()
« Reply #10 on: October 23, 2014, 11:02:21 PM »
Can not be used in UIPlayTween. :'(
OK!
Thank you! :) :)