Why Doesn’t _root.gotoAndPlay() Work with Scenes?
You may have seen this one in the forums; it comes up from time to time. Everyone knows that gotoAndPlay() supports Scene names as an optional parameter, right? You can either supply a frame number or frame label …
gotoAndPlay(15);
gotoAndPlay("roll-out animation");
… or a Scene name and a frame number …
gotoAndPlay("game over", 1);
… and that works. So what’s the deal? — why does it break if you specify _root (or some other path) in front of that gotoAndPlay() function?
Doppelgänger
The answer involves what may come as a surprise if you haven’t studied the MovieClip class entry of the ActionScript Language Reference. There are, in fact, two versions of gotoAndPlay(): the global function (the very function we’re discussing, here) and the MovieClip.gotoAndPlay() method. Methods are like functions, but are specific to a given class. (For more information on classes in general, see Objects: Your ActionScript Building Blocks, elsewhere in this blog.)
When you supply a prefix of any kind to a function, such as _root.gotoAndPlay(), you’re no longer referring to a function, but to a method of the object in question. _root refers to the main timeline, and believe it or not, the main timeline is a movie clip (in fact, the whole published SWF is one big movie clip). So, to understand what’s going on here, we have to investigate the MovieClip.gotoAndPlay() entry of the ActionScript Language Reference. I quote from the Parameters section …
frame:Object - A number representing the frame number, or a string representing the label of the frame, to which the playhead is sent.
Notice, no mention of Scenes. In a nutshell, then, that’s it: _root.gotoAndPlay() — or this.gotoAndPlay(), or this._parent.gotoAndPlay(), etc. — doesn’t accept Scenes because the MovieClip.gotoAndPlay() method doesn’t.
Working around it
What to do? You’re scoped to a button, perhaps, and need to refer to the main timeline in order to specify a Scene. Here’s the best approach.
Put simply, forego Scene names altogether when dealing with ActionScript. I’m not saying you need to forego Scenes — they’re a good, organizational design convenience during the authoring process — but all you really need is a unique frame label at each of your points of interest. It doesn’t matter what Scene they belong to, this.gotoAndPlay("frame label here"); (or _root.gotoAndPlay();) will work just fine. Problem solved.
If, for some reason, you’re absolutely stuck on using the function version, you could write a function of your own — let’s call it gotoSceneAndPlay() — that accepts the expected two parameters and passes them along, but there’s a catch: the optional Scene parameter for gotoAndPlay() must be a quoted string. So you couldn’t simply accept a scene:String parameter and use that. (Try it, and watch the compiler complain!) You would have to use an if or switch statement to evaluate the string and invoke gotoAndPlay() with something quoted …
function gotoSceneAndPlay(scene:String, frame:Number):Void {
switch(scene) {
case "uno":
gotoAndPlay("uno", frame);
break;
case "dos":
gotoAndPlay("dos", frame);
break;
case "tres":
gotoAndPlay("tres", frame);
break;
}
}
Tedious, to say the least. Stick with frame labels!
A bit of history
I should point out that in general, gotoAndPlay() the function, with or without Scenes, is something to avoid. Just chalk it up as one of those gotchas that occurs in every IDE, platform, or language developed by any software company. If your code is in the main timeline, simply use this.gotoAndPlay() to throw yourself into method mode. Why?
The macromedia.com ActionScript forum archives spell it out, so you’ll have to search a bit. The most helpful thread I can think of is one named “Scene Bliss” from mid-May, 2005. Use something like Google Groups to search the phrase “Jeckyl Stiller Cadillacula gotoAndPlay” and you’ll find it. It’s a looooong thread and gets somewhat emotional at times, so perform an in-page search for Jeckyl’s input if you want to cut to the chase.
Note, there are actually a handful of such “Doppelgängers” in ActionScript — duplicateMovieClip(), gotoAndStop(), loadMovie(), play(), and stop(), to name an additional few. Most, if not all, have to do with movie clips. Since Flash 5, and especially since Flash MX (aka Flash 6), ActionScript has taken more and more of an OOP approach. The newer classes are, well, newer, so it’s reasonable to conclude they’re better built (less prone to the occasional bug from previous incarnations). For backwards compatibility, the function versions are still around.
When you see one of these functions, take the initiative to check if a method version is available. The version to use is, of course, up to your own good judgment, but make sure your judgment is informed. There are subtle differences between the two versions of many of these Doppelgängers, so choose the one that best suits your needs.
March 27th, 2006 at 11:03 pm
My T-shirt from today’s lesson reads: “Tedious, to say the least. Stick with frame labels!”
March 28th, 2006 at 2:40 pm
It’s better to forego scenes (like _root!) - there are very few cases where they are a good practice, often lead to bad practices or problems as described above, and they have been discouraged for several versions now. Let go of _root, and let go of scenes whenever possible (most of the time), and you’ll be a happier in the long run who won’t have to keep track of all the gotchas.
March 28th, 2006 at 3:08 pm
magical unicorn,
For sake of clarity, I’ll mention that Scenes and _root aren’t the same thing.
_root is a global property that refers “to the root movie clip Timeline,” what people often refer to as the main timeline, and if multiple levels are used (
_level1,_level2, etc.), the “root movie clip Timeline is on the level containing the currently executing script. For example, if a script in level 1 evaluates _root, _level1 is returned” (_root property entry, ActionScript 2.0 Language Reference).Scenes, on the other hand, are not represented by objects in ActionScript at all (p. 713, Moock’s ActionScript for Flash MX: The Definitive Guide, Second Edition). When a SWF is compiled, Scenes collapse into a single timeline. All ActionScript knows at that point are frames and frame labels.
That said, it’s true that
_rootusage is often discouraged. In fact, the documentation makes mention of this under the “Avoiding absolute targets (_root)” topic of “Learning ActionScript 2.0 in Flash.” Personally, I don’t so much avoid_rootas make sure that when I use it, I do so on purpose and know the reason(s) why. Sounds like the makings of a blog entry. Thanks for the input!March 28th, 2006 at 9:39 pm
Very well aware of what both features are - I think you misunderstood my comment. I meant it’s best to avoid both of those - like I say, both lead to bad practices or problems, and both are discouraged (officially, and general community/Flash best practice). And actually, the fact that all scenes are compiled to a single timeline is what causes many of the problems for users (their code, etc) in the first place. And when this occurs, it is very hard for them to figure out why - hence, avoiding scenes whenever possible.
There are many existing blog entries on avoiding _root, many of which are an interesting read, indeed.
March 28th, 2006 at 9:55 pm
Ahh, my bad. You’re right, I misunderstood … when I read “It’s better to forego scenes (like _root!),” I took that to mean you were saying
_rootwas a Scene.April 12th, 2007 at 11:41 am
Thanx A lot man!!
i was really needing this expl.!!!
thanx Again!
May 7th, 2007 at 12:15 pm
Very Helpful, trying to pass a string variable from one keyframe to another so i could use it in gotoAndPlay() was driving me nuts.
May 13th, 2007 at 8:12 pm
Pablo, Chad …
Glad to help!
June 10th, 2007 at 8:55 pm
unlike what magical unicorn said above, _root shouldn’t be avoided, especially when your making a game where a global variabels such as those containing points need to be referenced.
December 26th, 2007 at 3:50 pm
Thanks for the discussion. I was struggling to figure this out on my own. Reading these comments saved me a lot of time and aggravation!
December 27th, 2007 at 7:10 pm
Paul,
Glad to hear that!
October 9th, 2008 at 3:22 pm
Menzoic,
Heh … this is probably the latest reply I’ve written yet (over a year old!), but I wanted to at least respond for the benefit of other readers. Like you, I maintain that
_rootisn’t something to avoid at all costs, but please be aware that the usage you’re describing — namely, games with globally accessible variables — does not require_rootin any way._rootdoes make a quick shortcut, but it’s never necessary.