Jump to content
Search Community

Timeline animation stutters - what am I doing wrong?

Majiy test
Moderator Tag

Recommended Posts

I´m trying my first test-application with TweenLight and TimelineLight.

 

If I use the TweenLite.to(...) method, everything runs smoothly.

 

Then I tried to do the same with a timeline.

First I tried to simply append new tweens like this:

private function onButtonGoToPosition():void {
timeline.append( new TweenLite( myTestObject, 1, { x:TEST_X, y:TEST_Y } ) );
}

 

But if I did it like this, the animation didn´t run every time I clicked the button.

 

So I tried like this:

private function onButtonGoToPosition():void {
timeline.append( new TweenLite( myTestObject, 1, { x:TEST_X, y:TEST_Y } ) );
timeline.play();
}

 

If I do it like this, the animation does rune (every time), but sometimes (around 50% of the times) the animation stutters or is skipped.

 

Am I doing something wrong?

Link to comment
Share on other sites

every time you press your button you are appending / ADDING a NEW tween to the timeline.

if you press the button 30 times, you have CREATED 30 new tweens back to back in one timeline.

 

when you tell a timeline to play(). it plays from the "virtual playhead's" current position... not from the beginning of the timeline. This concept can take some getting used to but is quite sound.

 

 

if you simply want your animation to play everytime the button is pressed do this:

 

//this creates a timeline containing 1 tween
var timeline:TimelineLite = new TimelineLite();
timeline.append( new TweenLite( myTestObject, 1, { x:TEST_X, y:TEST_Y } ) );

//this will make the timeline play from the begininng
private function onButtonGoToPosition():void {
  timeline.restart();
}

 

I understand you are just experimenting which is totally fine and it makes sense to start small. timelineLite really shines when you sequence multiple tweens... so once you get the above to work try this:

 

 

var timeline:TimelineLite = new TimelineLite();

timeline.append( new TweenLite( myTestObject, 1, { x:TEST_X, y:TEST_Y } ) );

timeline.append( new TweenLite( myTestObject, .5, { alpha:.5 } ) );

timeline.append( new TweenLite( myTestObject, .5, { rotation:180 } ) );

timeline.append( new TweenLite( myTestObject, .5, { alpha:1 } ) );

 

 

private function onButtonGoToPosition():void {

timeline.restart();

}

Link to comment
Share on other sites

every time you press your button you are appending / ADDING a NEW tween to the timeline.

if you press the button 30 times, you have CREATED 30 new tweens back to back in one timeline.

 

Yes, I know, that is what I am intending to do.

 

What I intended to say:

When I didn´t include the timeline.play() command after every appending, the animation would sometimes not start at all, or only after several seconds had passed.

 

Im am just confuse, because the same animation runs perfectly smooth when I use TwenLight.to(), but when I use the timeline, the animation begins to stutter and sometimes seems to be skipped in large parts.

 

For example:

Random Object should tween 100 pixels to the right.

 

Without timeline:

timeline.append( new TweenLite( myTestObject, 1, x:newX } ) );

This runs perfectly smooth, every time.

 

With timeline:

timeline.append( new TweenLite( myTestObject, 1, { x:newX} ) );
timeline.play();

Sometimes this runs good, sometimes it stutters, sometimes for a time nothing happens and then there is a big "jump" in the animation.

Link to comment
Share on other sites

you haven't exposed any code on how newX is being generated so its possible that:

 

1: the value of newX is sometimes the same as the object's start position so no movement will be rendered.

2: the value of newX may be so drastically different than the object's start position that it causes a big jump.

 

in the last bit of code you provided you stated : without timeline and then provided code that clearly references a timeline.

 

i'm having a tough time understanding what the intended behavior is. are you trying to create a long sequence of tweens that need to play in succession or do you just need the object to tween to a new position every time a button is pressed? if the latter, there is no need for a timeline.

 

perhaps you can provide an fla with a description of what should happen and I can take a look at it.

Link to comment
Share on other sites

in the last bit of code you provided you stated : without timeline and then provided code that clearly references a timeline.

 

Copy/paste error :oops:

 

i'm having a tough time understanding what the intended behavior is. are you trying to create a long sequence of tweens that need to play in succession or do you just need the object to tween to a new position every time a button is pressed? if the latter, there is no need for a timeline.

 

perhaps you can provide an fla with a description of what should happen and I can take a look at it.

 

My intention is to have a chain of animations, one after another. For testing, I append the animations with buttons.

 

I´m giving you the full code, maybe you can replicate this behaviour.

 

Main.mxml

 

(note the USE_TIMELINE constant)

 

<?xml version="1.0" encoding="utf-8"?>
		   xmlns:s="library://ns.adobe.com/flex/spark"
		   xmlns:mx="library://ns.adobe.com/flex/mx"
		   xmlns:lb="*"
		   width="960"
		   height="540"
		   creationComplete="init()"
		   >



































 

TestObject.mxml

 

(basically just a SkinnableContainer with a stroke and a filled rectangle)

 

<?xml version="1.0" encoding="utf-8"?>
				  xmlns:s="library://ns.adobe.com/flex/spark"
				  xmlns:mx="library://ns.adobe.com/flex/mx"
				  xmlns:local="*"
				  width="100"
				  height="130"
				  alpha="1"
				  >















Link to comment
Share on other sites

I can't do anything with the code you provided as I'm using Flash CS4 but I was able to replicate the issue you have described.

 

 

if the end goal is to be able to add new tweens to a timeline and have it constantly play I tried the following:

import com.greensock.*;
import com.greensock.easing.*;

var count:Number=0;
var tl:TimelineLite = new TimelineLite();

btn.addEventListener(MouseEvent.CLICK, addIt);



function addIt(e:MouseEvent):void {


if (count%2==0) {

	trace("even");
	tl.append(TweenLite.to(box, 2, {x:400, onStart:getStartX, onUpdate:getX}));


} else {


	trace("odd");
	tl.append(TweenLite.to(box, 2, {x:0, onStart:getX, onUpdate:getX}));


}

trace("currentProgress " + tl.currentProgress);
       count++;
tl.play();

}

function getStartX() {
trace("**** startX *** " + box.x);
}


function getX() {
trace(box.x);
}

 

to maintain tweens with equal distance and time I'm just tweening an object back and forth / left to right over a distance of 400 pixels.

it does in fact seem that the behavior is unpredictable.

 

more often than not, the first tween does jump about 90% its total distance before animating smoothly.

if I press the btn in quick succession a series of tweens will be generated that play nicely in sequence... but every now and then there is a noticeable jump or stutter.

I'm thinking that calling a play in the same instant an append() is called is doing something funky. more often than not, my understanding of what should happen is a bit askew.

 

 

I don't know what exactly is the cause. I'll see if I can get some additional help.

 

 

Carl

Link to comment
Share on other sites

Yeah, I can see why that looked like funky behavior. Let me explain...

 

The tweening platform has a root timeline (actually 2: one for regular tweens/timelines and another for frames-based tweens/timelines) that is basically always playing. Imagine a MovieClip timeline that has unlimited frames and it starts playing when your swf begins. Then, when you create a tween or a TimelineLite/Max, it gets dropped onto that root timeline at that particular point in time. Let's say you create a TimelineLite 5 seconds after your swf begins playing - that tween would have its startTime set to 5. That's all transparent to you.

 

In your case, you created the TimelineLite and didn't pause it initially, so it played. Since it was empty, it completed on the very next frame. If you had an onComplete, you'd see it fire almost immediately.

 

Now let's say you append() a 6-second tween to that TimelineLite 3 seconds later (so now we're at a global time of 8). Try to envision where that tween would be scheduled in terms of the global timeline. The parent TimelineLite that you append() it to has a startTime of 5. Since your TimelineLite was empty, append() will insert it at the very start of that TimelineLite (startTime:0). Remember, though, that the root timeline is at 8 seconds now. So when it renders that TimelineLite, it will now be 3-seconds deep. Your 6-second tween would render halfway done (3 seconds).

 

So why did it appear to work if you call play() first before appending? Because there was code in the play() method that basically said "if this TimelineLite/Max is already done, adjust its startTime so that the playhead lands on its currentTime right now". That was primarily for convenience, to give developers what they'd most likely want. When you play() first, your Timeline was empty so it had already been finished thus it tripped this code. But when you append() a tween (as long as the duration exceeds the time that has already elapsed), it re-enables that TimelineLite so that when you then play() it, that code says "is the timeline already done? Nope. Okay, proceed normally and don't adjust the startTime..."

 

Confused yet?

 

Anyway, I just uploaded a new version of TimelineLite/Max that adds some convenience code which should solve this issue for you. If the TimelineLite/Max is on TweenLite's root/master timeline and has already completed when you insert/append a child tween/timeline, it will automatically adjust the startTime accordingly. I only do that on the root ones because typically if you've got it nested inside another TimelineLite/Max, you'd want the startTime honored (not adjusted).

 

If that all made no sense whatsoever, don't worry. Just download the latest version and it should work well for you. I'd appreciate hearing back from you to confirm, though.

 

Link to comment
Share on other sites

i had to read the 4th paragraph 4 times very slowly... but it actually does make sense to me now knowing how the tweening platform's root timeline manages the various relative start times and such. nice job.

 

the whole part about why it appeared to work if play was called first trips me up a bit, but don't worry about that. I'm sure it will sink in.

 

thanks so much for the help and adjusting the platform to be more intuitive for us!

 

Carl

 

ps. i did not download the most recent greensock files and yet I can not get my original file with the append() then play() to get all funky. not even once. its like the issue fixed itself... very very strange.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...