Author Topic: Tweening Related Problems  (Read 7725 times)

hillinsilence

  • Newbie
  • *
  • Thank You
  • -Given: 1
  • -Receive: 0
  • Posts: 5
    • View Profile
Tweening Related Problems
« on: November 18, 2015, 11:15:18 PM »
Hi,

After tracking down some issues in our project these days, I think there are some problems with NGUI's tweening. Please correct me if I'm wrong.

1. UITweener calls an Update() immediately after Play() or Start() is called. This will make the current frame's deltaTime count in the total duration. When I call Play() or Start(), I'm actually expecting the tween to start exactly the time I call it, rather than some milliseconds before. Besides the inaccuracy in time control and visual flaws it caused, if the current frame is a quite long one while the tween duration is short, this could cause an even more critical problem: the tween will finish immediately, right after Play() or Start() is called, following by its onFinished callback. This leads to the second problem:

2. UIPlayTween iterates through all the tweens, find out those matching the specified tween group id, and do the following things to each of them: increase a zero-based counter by one, add an onFinished callback, and play it. In the onFinished callback, it then reduces the counter by one and see if it will become zero, which means all the tweens are finished playing, and it's time to invoke its own onFinished callback. All these worked perfectly except for one thing: if the first tween is rather short in duration, problem 1 could be triggered and the tween will finish instantly. Tween counter will be increased to 1 and reduced to 0 right away, then UIPlayTween's onFinished callback will be invoked - actually there are still many tweens not started yet. If the second tween is also very short, the procedure will repeat and the UIPlayTween's onFinished callback could be invoked multiple times, in one frame, leading to unexpected behaviors.

There is a simple solution to problem 2, we can split the iteration, count first, then play the tweens. This will ensure the onFinished callback to be invoked only once, however problem 1 is still the prime.

There is also a mechanism to prevent re-entrancy in UIPlayTween's OnFinished method. This mechanism is problematic with problem 1 if you want to chain up multiple UIPlayTweens. I guess it's no longer needed if problem 1 is resolved, too.

3. UIPlayTween tends to play a tween twice if resetOnPlay is set to true. It first plays the tween, then rewind it to the beginning, and play it again. I suspect there are special reasons to do so, however I can't figure it out. As with problem 1, the onFinished callback of the tween could be invoked twice in this circumstance.

Something weird is, these problems became quite significant after I updated my Unity to 5.2, from 5.0. They occurred sparsely and randomly in 5.0, caused some minor visual flaws so I didn't care about them (have a full list of more important things to do). However in 5.2, a great amount of short-time tweens disappeared from my app. I upgraded my NGUI to 3.9.4, too, not helpful.

Any idea would be appreciated.
« Last Edit: November 18, 2015, 11:25:34 PM by hillinsilence »

hillinsilence

  • Newbie
  • *
  • Thank You
  • -Given: 1
  • -Receive: 0
  • Posts: 5
    • View Profile
Re: Tweening Related Problems
« Reply #1 on: November 20, 2015, 12:28:38 AM »
Here is a quick fix to problem 1, and consequently problem 2: add this line
  1. delta = 0;
in the if(!mStarted) block in UITweener.Update.

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Tweening Related Problems
« Reply #2 on: November 25, 2015, 05:08:48 PM »
Here is a quick fix to problem 1, and consequently problem 2: add this line
  1. delta = 0;
in the if(!mStarted) block in UITweener.Update.
That's a good suggestion, thanks! I'll add it to my repository and see if it works as expected.

I don't quite understand your point #3 though... resetOnPlay is used only on line 314 of UIPlayTween, which is a part of the Play() function. So when the UIPlayTween.Play is called, it will effectively happen only once and at the very beginning. I just did a quick test -- two sprites, one sprite with a (disabled) TweenAlpha on it set to tween from 0 to 1, another sprite with a collider and UIPlayTween on it with On Activation set to "RestartTween" (which is what resetOnPlay set to 'true' does). Clicking on the second sprite starts the tween on the first one, and it only plays once.

hillinsilence

  • Newbie
  • *
  • Thank You
  • -Given: 1
  • -Receive: 0
  • Posts: 5
    • View Profile
Re: Tweening Related Problems
« Reply #3 on: November 27, 2015, 03:29:34 AM »
That's a good suggestion, thanks! I'll add it to my repository and see if it works as expected.

I don't quite understand your point #3 though... resetOnPlay is used only on line 314 of UIPlayTween, which is a part of the Play() function. So when the UIPlayTween.Play is called, it will effectively happen only once and at the very beginning. I just did a quick test -- two sprites, one sprite with a (disabled) TweenAlpha on it set to tween from 0 to 1, another sprite with a collider and UIPlayTween on it with On Activation set to "RestartTween" (which is what resetOnPlay set to 'true' does). Clicking on the second sprite starts the tween on the first one, and it only plays once.

Just check the code around line 314, if resetOnPlay is true, all tweens governed by that UIPlayTween will get their Play() (UITweener.Play, not UIPlayTween.Play) called twice. Each of them will be played, reset to beginning, and played again. In most cases ,the first Play() call will only do some initialization and will be overridden by the latter one. However if problem 1 persists, UITweener.onFinished could be invoked twice.


ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Tweening Related Problems
« Reply #4 on: December 01, 2015, 07:23:36 AM »
So fixing #1 fixes #2?

Mistborn

  • Newbie
  • *
  • Thank You
  • -Given: 1
  • -Receive: 0
  • Posts: 6
    • View Profile
Re: Tweening Related Problems
« Reply #5 on: December 21, 2015, 12:54:55 AM »
In 3.9.6, I noticed that the tweener doesn't behave properly. According to the fix in 3.9.6: "Tweener will no longer use delta time for the first frame of the animation." Is it a mistake to set delay to zero in the if(!mStarted) block in UITweener.Update? Maybe following code is what you want?

  1. if (!mStarted)
  2. {
  3.         delta = 0;
  4.         mStarted = true;
  5.         mStartTime = time + delay;
  6. }
  7.  

diederik

  • Newbie
  • *
  • Thank You
  • -Given: 1
  • -Receive: 2
  • Posts: 31
    • View Profile
Re: Tweening Related Problems
« Reply #6 on: December 22, 2015, 02:26:15 PM »
Hi Mistborn,

Not really understand the problem in this thread, but I do know that all my tweener start delays started malfunctioning since I updated to 3.9.6.
So I changed the UITweener.cs the way you described and now it seems to work again!!!

The 3.9.6 version might have fixed a pecular problem, but let's not break basic functionality people! ;)

Thanks for the fix (I hope) and a merry christmas Mistborn!

Diederik / Xform

S3dition

  • Newbie
  • *
  • Thank You
  • -Given: 0
  • -Receive: 0
  • Posts: 5
    • View Profile
Re: Tweening Related Problems
« Reply #7 on: December 22, 2015, 05:57:03 PM »
On this note, start delay doesn't appear to work anymore. I'm not seeing other mention of it in my searches. Is this a known problem?

ArenMook

  • Administrator
  • Hero Member
  • *****
  • Thank You
  • -Given: 337
  • -Receive: 1171
  • Posts: 22,128
  • Toronto, Canada
    • View Profile
Re: Tweening Related Problems
« Reply #8 on: December 23, 2015, 09:36:47 AM »
Hmm... you are correct, Mistborn. Thanks!