Monday, June 21, 2010

Notorious Tween and the Garbage Collector Issues

I love tween and use it a lot while making websites and applications. But whenever I use more than 3 tweens simultaneously it doesn't work properly. It works sometimes and sometimes it just freezes in the middle and any Event Listener that has been called is not triggered. Moreover it works on some computer and in some it doesn't.

Before I tell you how to fix it let me explain why it happens. Flash player runs GC (Garbage Collector) once it executes the script. It does this to free up the memory and enhance the performance. Now they way flash player runs the GC depends on the system resource. So if the users computer has less memory GC is triggered earlier and if the user runs the program on the same computer when more memory is available it triggers the GC little late.

Most of the time tween gets stuck if you have code like below where the tween time is different.

var a:Tween = new Tween(a_mc, "y", Back.easeIn, -75, 0, 1, true);
var bTween = new Tween(b_mc, "y", Back.easeIn, -75, 0, 2, true);
var c:Tween = new Tween(c_mc, "y", Back.easeIn, -75, 0, 3, true);
c.addEventListener(TweenEvent.MOTION_FINISH, loadThis);

function loadThis(e:TweenEvent):void
{
trace ("It's Loaded");
}

here the Flash Engine runs all the scripts at same time and when the first tween is finished the GC disables all the tweens. A better way to code is to change the starting "y" axis.

var a = new Tween(a_mc, "y", Back.easeIn, -95, 0, 1, true);
var b = new Tween(b_mc, "y", Back.easeIn, -85, 0, 1, true);
var c = new Tween(c_mc, "y", Back.easeIn, -75, 0, 1, true);

function loadThis(e:TweenEvent):void
{
trace ("It's Loaded");
}


this way, the tween finishes at the same time, the movie clips reaches the destination in different time like the previous code and have less change to effected by GC. Now, this is not the foolproof. It still gets stuck once in a while. This is the issue with Flash Player and there is not way out, for at least now. The issue gets even worse when functions are triggered based on the Event Listener.

To make sure that the functions are running even when the tween gets stuck we can create timer function. In this function we can run a conditional statement to check if the tween has completed and the event has triggered. Here is the code for that

var activated:Boolean;
var myTimer:Timer = new Timer(1010,1);

var a = new Tween(a_mc, "y", Back.easeIn, -95, 0, 1, true);
var b = new Tween(b_mc, "y", Back.easeIn, -85, 0, 1, true);
var c = new Tween(c_mc, "y", Back.easeIn, -75, 0, 1, true);

function loadThis(e:TweenEvent):void
{
activated = true;
trace ("It's Loaded");
}

myTimer.start();
myTimer.addEventListener(TimerEvent.TIMER, checkTween);

function checkTween(e:TimerEvent):void
{
if(activated == false)
{
trace("It's Loaded");
}
if(a_mc.y <=-1 || b_mc.y <=-1 || c_mc.y <=-1)
{
a_mc.y = b_mc.y = c_mc.y = 0;
}
}

No comments:

Post a Comment