Author Topic: UIPlayTween problem  (Read 4577 times)

Zux

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 12
    • View Profile
UIPlayTween problem
« on: August 17, 2014, 08:34:03 PM »
Hi,I have a problem with UIPlayTween onFinished event here.
When I do play tween group 1 with UIPlayTween, and assign a method eventdelegate to it's onFinished, it works fine.
In the method I detach the method itself, and reset the played tweens group to zero.
But when I continues to set some other tweens group to 1, assign another onFinished method, and then play these tweens in this method, it goes strange. The new onFinished eventdelegate will be called immediately after UIPlayTween.play method is called, and makes the logic sequence confused.
I run the code and always, when I do play the tween from the start, the first always goes right, the immediate second play always goes unexpected.
I set a break in my method, and view the stack trace, it seemed the new onFinished method calling stack is normal, it's called from UIPlayTween onFinished method, and UITweener.Update method,but when I put debug codes in these functions, they didn't work inside the calling play method and onFinish delegate method.
After I did more debug, I find the new on Finish delegate method (named onreelimate) is called immediately after UIPlayTween.play method runned, and I can't find where is the caller. And if I remove the code in onreelimate which is to remove itself's eventdelegate, this method will be called again when the second tweens play end.

So here is the secord tween play code, beginRollback is called in the first tween onFinished  delegate method.
  1.         void beginRollback()
  2.         {
  3. ......
  4.                 UIPlayTween pt = (UIPlayTween)gameObject.GetComponent(typeof(UIPlayTween));
  5.                 EventDelegate eventDelegate = new EventDelegate(this, "onreelimate");
  6.                 teventDelegate = eventDelegate;
  7.                 eventDelegate.parameters[0] = new EventDelegate.Parameter(this, "teventDelegate");
  8.                 EventDelegate.Add (pt.onFinished, eventDelegate);
  9.                 Debug.Log ("playing reelimate at :" + System.DateTime.Now.ToLongTimeString ());
  10.                 pt.Play (true);
  11.         }
  12.  
  13.         void onreelimate(EventDelegate edelegate)
  14.         {
  15.                 Debug.Log ("finish reelimate at :" + System.DateTime.Now.ToLongTimeString ());
  16.                 UIPlayTween pt = (UIPlayTween)gameObject.GetComponent(typeof(UIPlayTween));
  17.                 EventDelegate.Remove (pt.onFinished, edelegate);
  18.         }
  19.  
and in the UIPlayTween, I add some debug codes in the play and onFinished method
  1.         public void Play (bool forward)
  2.         {
  3.                 Debug.Log ("start playing");
  4.                 mActive = 0;
  5.                 GameObject go = (tweenTarget == null) ? gameObject : tweenTarget;
  6. ......
  7.                                                 tw.Play(forward);
  8.                                         }
  9.                                 }
  10.                         }
  11.                 }
  12.                 Debug.Log ("end playing");
  13.         }
  14.  
  15.         void OnFinished ()
  16.         {
  17.                 if (--mActive == 0 && current == null)
  18.                 {
  19.                         Debug.Log ("on finish called at " + System.DateTime.Now.ToString ());
  20.                         current = this;
  21.                         EventDelegate.Execute(onFinished);
  22.  
  23.                         // Legacy functionality
  24.                         if (eventReceiver != null && !string.IsNullOrEmpty(callWhenFinished))
  25.                                 eventReceiver.SendMessage(callWhenFinished, SendMessageOptions.DontRequireReceiver);
  26.  
  27.                         eventReceiver = null;
  28.                         current = null;
  29.                 }
  30.         }
  31.  

and log result in the attach.
The tween duration is set to 2 seconds, and the onreelimate method debug time is same as the caller beginRollback debug time.
And if code
  1. EventDelegate.Remove (pt.onFinished, edelegate);
is removed, there will be another calling debug output 2 seconds later.
« Last Edit: August 18, 2014, 02:59:04 AM by Zux »

Zux

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 12
    • View Profile
Re: UIPlayTween problem
« Reply #1 on: August 18, 2014, 06:58:41 AM »
I believe this is a bug, for when I use a new UIPlayTween Component in the delegate method, it works fine now.
I just create a new empty object, add another UIPlayTween Component, and use this one to play the second tween group, all goes as expected.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: UIPlayTween problem
« Reply #2 on: August 18, 2014, 12:46:20 PM »
If you examine the code for UITweener.cs around line 218 you will notice that it doesn't use the same list when executing the callbacks. It makes a copy instead.

If you want to remove callbacks on execution, you should specify it as an option when doing EventDelegate.Add. It's an optional boolean parameter (one shot).

Zux

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 12
    • View Profile
Re: UIPlayTween problem
« Reply #3 on: August 19, 2014, 06:19:08 AM »
If you examine the code for UITweener.cs around line 218 you will notice that it doesn't use the same list when executing the callbacks. It makes a copy instead.

If you want to remove callbacks on execution, you should specify it as an option when doing EventDelegate.Add. It's an optional boolean parameter (one shot).
Thanks,  I noticed the parameter oneshot but didn't realize it's usage. But this parameter doesn't affect the problem,  yeah?

Zux

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 12
    • View Profile
Re: UIPlayTween problem
« Reply #4 on: August 19, 2014, 08:07:30 AM »
And, I tested a third tween in the second tween onfinish delegate method, this time is something different from the second, thus use a new third UIPlayTween component of course goes as expected, and reuse of the second UIPlayTween component goes wrong, but reuse of the first UIPlayTween component is correct.
This may solve a logic problem: If I have a looped logic, I don't need to create or add a new UIPlayTween component when I need to play a tween group in logic.

Zux

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 12
    • View Profile
Re: UIPlayTween problem
« Reply #5 on: August 22, 2014, 08:29:41 AM »
Hi, I have finished my first step demo now, and I believe what I posted here is realy a bug.
For now, I use Instantiate a prefab object with an UIPlayTween component each time when I need to play a tween group, and destory the object in the onFinish delegate method, it goes well.

But when I try to reuse any UIPlayTween component binded to any existing object, there will soon be some objects with tweens goes unexpected, logics breaked, and some blocks position lost.

I don't know whether this is because I do change the tween parameters dynamicly in the logic.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: UIPlayTween problem
« Reply #6 on: August 23, 2014, 03:06:35 AM »
You need to use NGUITools.AddChild to instantiate widgets, not Object.Instantiate. You are likely causing some property to update before the widget's parent was set, which causes it to find a panel. Then you reparent it, setting its parent, but never notify it that you've done so (NGUITools.MarkParentAsChanged). NGUITools.AddChild sets the parent right away.

Zux

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 12
    • View Profile
Re: UIPlayTween problem
« Reply #7 on: August 23, 2014, 04:08:17 AM »
You need to use NGUITools.AddChild to instantiate widgets, not Object.Instantiate. You are likely causing some property to update before the widget's parent was set, which causes it to find a panel. Then you reparent it, setting its parent, but never notify it that you've done so (NGUITools.MarkParentAsChanged). NGUITools.AddChild sets the parent right away.
I checked out my code and confirmed that all my NGUI widgets (only 8x8 UISprites) are instantiated using NGUITools.AddChild, and the prefab GameObject which I use Object.Instantiate to create is an empty object with only an UIPlayTween component, and I'm sure that there is no reparent action in my code. I only do reset position,  tween positions, tween rotations and tween scales of these sprites.

Zux

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 12
    • View Profile
Re: UIPlayTween problem
« Reply #8 on: August 23, 2014, 08:15:45 AM »
More problems here.
My logic is : user action begin a round, play tweens, count logics, play tweens, and more logics with tweens until round logic done.
When I finished one round, then rotating and scaling all sprites to disappear, reset data and spriteName, then play back. Here I just use the UIPlayTween's play(true) to make them disappear, and when finish, do reset data, then use play(false) to reverse tween play and show the sprites.
But in next round when user acted, logic breaks with one added event doesn't respond again.
And after test, I found that I have to manually set all tweens from and to value(just inverse them), and call resetToBegin(), then use play(true),  this time next round is OK. And I tested, it can goes well for decades of rounds.