When a nested MovieClip with a custom subclass is created, the order is something like this (I think):
- the asset is created (as a “plain” MovieClip: it has its name, dimensions, etc, and can be referred to by name from the containing MovieClip, but it has no methods or properties of its ActionScript class)
- its constructor is called
- any
onLoad()
handler is called
- frame scripts on the MovieClip’s timeline execute
[UPDATE: It looks like Colin Moock‘s excellent book Essential ActionScript 2.0 talks about this very situation, on page 328. His workaround is to use setInterval
to poll the object to see if the custom methods/properties have been set up yet.]
This kind of stuff is always a bit difficult to describe clearly, so I might not even try :P So here are some scratched-in notes for myself:
- Imagine a MovieClip (mc1) which contains another MovieClip inside it (mc2). This nested instance is created in the authoring tool. It would look like this in the Movie Explorer:
- Both MovieClips have (different) custom class: let’s call them
MovieClass1
and MovieClass2
.
The constructor for MovieClass1
looks like this:
class MovieClass1 extends MovieClip {
function MovieClass1()
{
trace("MovieClass1 ctor " + this);
}
} |
class MovieClass1 extends MovieClip {
function MovieClass1()
{
trace("MovieClass1 ctor " + this);
}
}
MovieClass2
‘s constructor looks shockingly similar:
class MovieClass2 extends MovieClip {
function MovieClass2()
{
trace("MovieClass2 ctor " + this);
}
} |
class MovieClass2 extends MovieClip {
function MovieClass2()
{
trace("MovieClass2 ctor " + this);
}
}
Ok. Now we place an instance of MovieClass1
on the stage, name it mc1
, and test the movie. Here is the traced output:
MovieClass1 ctor _level0.mc1
MovieClass2 ctor _level0.mc1.mc2 |
MovieClass1 ctor _level0.mc1
MovieClass2 ctor _level0.mc1.mc2
So we know that the constructor for the parent clip is called before the constructor of the child clip.
Note that this is quite unlike C++, for example, where member objects are created before the containing object’s constructor is called (see here for an example), and in fact can cause real issues. For example, suppose MovieClass1
‘s constructor wants to call custom methods of MovieClass2
. Those calls will fail because mc2 has not yet been initialized! Note that this only applies to methods and properties that exist in the custom class — the MovieClip exists, as a plain old MovieClip
, but the custom class hasn’t been associated with it yet.
Example:
MovieClass1.as:
class MovieClass1 extends MovieClip {
var mc2:MovieClip; /* placed in Flash authoring tool */
function MovieClass1()
{
trace("MovieClass1 ctor " + this);
mc2.customMethod();
}
} |
class MovieClass1 extends MovieClip {
var mc2:MovieClip; /* placed in Flash authoring tool */
function MovieClass1()
{
trace("MovieClass1 ctor " + this);
mc2.customMethod();
}
}
MovieClass2.as:
class MovieClass2 extends MovieClip {
function MovieClass2()
{
trace("MovieClass2 ctor " + this);
}
function customMethod()
{
trace("MovieClass2 customMethod()");
}
} |
class MovieClass2 extends MovieClip {
function MovieClass2()
{
trace("MovieClass2 ctor " + this);
}
function customMethod()
{
trace("MovieClass2 customMethod()");
}
}
The results of running this test:
MovieClass1 ctor _level0.mc1
MovieClass2 ctor _level0.mc1.mc2 |
MovieClass1 ctor _level0.mc1
MovieClass2 ctor _level0.mc1.mc2
Yep. customMethod()
is never called!
I hope to continue this in a later post… there are more details about the constructor-calling process that are weird and intriguing!
This is the first in what I hope to be a series of articles about execution order in Flash. That is, when scripts can be placed on MovieClips, Buttons, timeline frames, event handlers etc, in what order will they execute when the movie is running?
A recent bug in my code inspired these investigations. The results are quite interesting, although I have not come to any hard-and-fast conclusions yet.
But first, a simple experiment:
In a new Flash movie, create a simple MovieClip consisting of two frames. Add some text or some other visual aid, if you like. Then add a script in frame 1 that simply reads: trace("Timeline 1, Frame 1");
In the library pane, make a copy of that MovieClip. Then edit the text inside it (so you can distinguish it from the first), and change the script to read trace("Timeline 2, Frame 1");
Now edit the first MovieClip, and drag an instance of the second into the first. Then place an instance of the first MovieClip on your stage.
I hope that made sense!
Here’s what it might look like in the Movie Explorer window:
You might also want to set the frame rate of the movie to 1 frame per second, so that it’s easier to watch all the trace()s in the output window.
Now run the movie, and stop it after a few frames have written to the output window. Take a look at the first lines of trace():
Timeline 1, Frame 1
Timeline 2, Frame 1
Timeline 2, Frame 1
Timeline 1, Frame 1
Timeline 2, Frame 1
Timeline 1, Frame 1
...
Notice anything unexpected?
At the very beginning of the movie, MovieClip 1’s script runs before MovieClip 2. But after that first frame, MovieClip 2’s script executes before MovieClip 1!
I don’t know the reason behind this, but Flash is full of interesting behaviour like this when it comes to execution order. I hope to explore this more in following posts, as well as providing a simple enhancement to trace()
that makes it easier to follow order of execution.
I’ve attached the sample FLA file in MX2004 format. Take a look and let me know what you think!