Monthly Archives: April 2009

Combine buttonMode = true and a mouse click to leak memory

Here’s a troublesome Flash Player bug I discovered when I couldn’t understand why my SWF wouldn’t unload properly from a parent SWF. Everything seemed to unload fine unless I clicked on any buttons in my game’s menus. How strange. I loaded my SWF up in the Flex Builder profiler and watched what stuck around. Sure enough, in addition to the main document class and anything referenced there, some button instances that should be gone seemed to be sticking around. The reason they were stuck in memory? I set buttonMode to true.

Sounds weird, right? At first, following my own recent advice on how to cleanup an unloading SWF, I started commenting out certain mouse events used by the buttons. My thinking was that maybe these event listeners were causing the stage to keep a reference to the button. Unfortunately, that didn’t seem to help. In frustration, I started commenting out large portions of the button class. With almost no code left to run, I got the SWF to unload properly. No instances of any class in my SWF were left this time, so it was clear that this button class was the culprit. I began slowly adding bits of functionality back in. I eventually discovered two functions that would cause the button to stay in memory, and both had one thing in common: they modified buttonMode. I re-enabled all my code in that class, except for the lines that set buttonMode, and the SWF began unloading perfectly.

That’s a pretty complex case that involves multiple SWFs, and it certainly wasn’t easy to debug. For my bug report to Adobe, I built a very simple test case that you can look at below. I simply creates two Sprite instances that are clickable, one with buttonMode set to true, and one without:

package
{
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	import flash.system.System;

	public class ButtonModeBug extends Sprite
	{
		public function ButtonModeBug()
		{
			var button1:Sprite = new Sprite();
			button1.graphics.beginFill(0x009900);
			button1.graphics.drawRect(0, 0, 120, 20);
			button1.graphics.endFill();
			button1.x = 10;
			button1.y = 50;
			button1.addEventListener(MouseEvent.CLICK, regularSpriteClickHandler);
			this.addChild(button1);

			var button2:Sprite = new Sprite();
			button2.graphics.beginFill(0x990000);
			button2.graphics.drawRect(0, 0, 120, 20);
			button2.graphics.endFill();
			button2.x = 150;
			button2.y = 50;
			button2.buttonMode = true;
			button2.addEventListener(MouseEvent.CLICK, buttonModeSpriteClickHandler);
			this.addChild(button2);
		}

		private function regularSpriteClickHandler(event:MouseEvent):void
		{
			var button1:Sprite = Sprite(event.currentTarget);
			button1.removeEventListener(MouseEvent.CLICK, regularSpriteClickHandler);
			this.removeChild(button1);
			button1 = null;
			System.gc();
		}

		private function buttonModeSpriteClickHandler(event:MouseEvent):void
		{
			var button2:Sprite = Sprite(event.currentTarget);
			button2.removeEventListener(MouseEvent.CLICK, buttonModeSpriteClickHandler);
			this.removeChild(button2);
			button2 = null;
			System.gc();
		}
	}
}

Notice that when you click either button, it is removed from the display list, the event handler is removed, the variable is set to null, and then System.gc() is called to force the garbage collector to run.

To see the bug in action, you should run that class in the profiler with live memory data displayed (you may need to unfilter the flash.* classes too). When you click button1 (the green one), you can see the number of Sprite instances decrease by one. When you click button2 (the red one), the number of Sprite instances stays the same.

As a control case, comment out the line that says button2.buttonMode = true;, and run again. Both buttons will be removed from memory, and the number of Sprite instances will decrease to zero.

The description of this bug can be summarized like this:

If you set buttonMode to true on a Sprite, and that Sprite gets clicked by the user, it will not be removed from memory after all references have been removed in ActionScript.

It appears, although I cannot be certain, that Flash Player’s internal code isn’t properly releasing its own reference to the Sprite. Maybe related to the hand cursor? Whatever the case may be, I recommend being wary of buttonMode (and the related useHandCursor) until this gets fixed, especially if you have a SWFs that are loaded and unloaded inside other SWFs. I say that because your buttons will hold many more objects in memory when the SWF can’t unload properly. If you’ve encountered the same bug, please vote for it in my report, “buttonMode = true + mouse click keeps Sprite in memory” filed in the public Adobe bug system.

Be a good SWF citizen, listen for Event.UNLOAD

If you have a SWF that you know will be loaded into a parent SWF, then it’s your responsibility as a developer to properly clean up after yourself when your child SWF is unloaded. Certain activities will keep your SWF in memory long after the unload() method is called on the Loader object that holds your child SWF, and there’s a good chance that you’ll have created a memory leak if you don’t take care of things properly.

It’s important to note that in Flash Player 10, Loader has a new unloadAndStop() method that does some of this work for you (see Grant Skinner’s blog post about unloadAndStop() for detailed information). While that’s helpful for SWFs that you don’t control, I think it’s still very important to clean up your own SWFs as best you can manually. Obviously, you have no other choice if you’re still targeting Flash Player 9.

What sorts of things could cause problems when you’re trying to unload a SWF? Running Timer instances, enterFrame events, audio or video that’s still playing or streaming, MovieClip instances that are playing, and content loaders that have not completed yet are all good examples (see Grant’s post above for a longer list). Some of these activities don’t actually keep your SWF in memory, but it’s important to remember that your SWF may not be garbage collected immediately. Code that’s still running for no good reason is simply a waste of resources.

How to clean up after yourself

A SWF can discover when it has been unloaded by listening for Event.UNLOAD on its loaderInfo object. This event handler is the perfect place to do your cleanup. I’ve put together a couple of very simple classes to illustrate how this process works.

First, we have the aptly-named ParentSWF document class for the SWF that loads our second SWF as a child. It’s very simple. It instantiates a Loader to load ChildSWF.swf. When that Loader has completed, it has some code to unload ChildSWF.swf right away:

package
{
	import flash.display.Loader;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.net.URLRequest;

	/**
	 * This is the document class for a parent SWF that loads, then unloads, a
	 * child SWF. It is part of a demonstration of how child SWFs can clean
	 * up after themselves up when they are unloaded.
	 *
	 * @author Josh Tynjala (joshblog.net)
	 */
	public class ParentSWF extends Sprite
	{
		public function ParentSWF()
		{
			super();

			//this loader will load the child SWF. Upon completion, it will
			//immediately unload the child SWF.
			this._loader = new Loader();
			this._loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loaderCompleteHandler);
			this._loader.load(new URLRequest("ChildSWF.swf"));
			this.addChild(this._loader);
		}

		private var _loader:Loader;

		private function loaderCompleteHandler(event:Event):void
		{
			this._loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, loaderCompleteHandler);
			this.removeChild(this._loader);

			//this is where we unload the child SWF
			this._loader.unload();
			this._loader = null;

			//at this point, the child SWF should be ready to be garbage
			//collected. only the child SWF can keep itself in memory now.
			//it had better clean up after itself!
		}
	}
}

Next, let’s take a look at ChildSWF, the document class for our second SWF that is loaded into the first SWF. It includes a running Timer that should be stopped when the child SWF is unloaded. We listen for Event.UNLOAD on loaderInfo to know when the parent SWF has unloaded the child SWF:

package
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.TimerEvent;
	import flash.utils.Timer;

	/**
	 * This is the document class for a child SWF is loaded in a parent SWF, and
	 * then unloaded. It is part of a demonstration of how child SWFs can clean
	 * up after themselves up when they are unloaded.
	 *
	 * @author Josh Tynjala (joshblog.net)
	 */
	public class ChildSWF extends Sprite
	{
		public function ChildSWF()
		{
			super();

			//we want to listen to Event.UNLOAD so that we know when the Loader
			//in the parent SWF has unloaded this SWF
			this.loaderInfo.addEventListener(Event.UNLOAD, unloadHandler);

			//this timer, if still running, will keep this SWF in memory after
			//ths SWF is unloaded.
			this._timer = new Timer(1000);
			this._timer.start();
		}

		private var _timer:Timer;

		private function unloadHandler(event:Event):void
		{
			//stop the Timer or this SWF won't be garbage collected
			this._timer.stop();

			//of course, make sure to remove this event listener too!
			this.loaderInfo.removeEventListener(Event.UNLOAD, unloadHandler);
		}
	}
}

To be perfectly clear, the most important parts of the child SWF code above can be summarized in the snippet below:

//listen for the unload event to know when all activities in this SWF should be stopped
this.loaderInfo.addEventListener(Event.UNLOAD, unloadHandler);

function unloadHandler(event:Event):void
{
	this.loaderInfo.removeEventListener(Event.UNLOAD, unloadHandler);

	//DO YOUR CLEANUP HERE!
}

Again, let me cover some of the most common things that should be cleaned up. Be sure to stop audio and video that is playing, MovieClip instances that no longer need to be playing, Timer instances, tweens (they’re probably run by Timer instances or enterFrame events), active listeners for any type of Event.ENTER_FRAME, listeners for events coming from the stage (also a good place to use a weak reference), and be sure to stop any data that may be loading from external sources using URLLoader, Socket, Loader, and other classes of that type. If your child SWF has it’s own child SWFs, be sure to unload those too!

That’s a lot of stuff to remember! Yes, it is, and it’s your responsibility as the developer to ensure that nothing in your SWF causes a memory leak, just like it’s your responsibility to do the same for your individual classes. If you’ve designed the rest of your application with good memory management, then it might not be as bad as you think. Often, you only need to take care of objects that are referenced in the document class. Those objects should already be doing their own work to cleanup any references and event listeners that aren’t needed anymore. For more information on that subject, check out the excellent series of blog posts about AS3 memory management by (once again) the very knowledgeable Grant Skinner.

A quick glance at my game development workflow

My recent excursion into Flash game development has been fun, to say the least. Certainly, I’ve finally been able to dive into more creative areas of Flash that I haven’t touched as much as I would have liked. It’s also enjoyable to be in charge of all aspects of a project from concept to conclusion. As much for self-exploration as for passing on knowledge, I want to share a little bit about certain aspects of my recent workflow. It won’t be a full inside-out dissection, but more a peek at some highlights that I think might be particularly interesting.

The Whiteboard

No matter what stage of game development in which I’m currently working, I keep a small hand-held whiteboard around. Most of the time, it just sits on my desk or the closest table, but it stays nearby for good reason. Firstly, it helps me immediately visualize current tasks that might be hard to fully imagine in my head. If I’m in the zone, I don’t want to run off searching for something to write on. I want to stay focused, draw on something that’s nearby, and instantly produce results. If something doesn’t look right, all it takes is a quick swipe to erase, and I can try something new.

I’ve found the whiteboard to be most useful when I get the very first idea for a new game. I’m not yet ready to code up a quick semi-playable prototype. I just want to physically see what has vaguely formed in my head. It’s very much a creative task where a simple drawing (that doesn’t even necessarily show interaction in any way) can make the idea more solid. It’s also the first line of defense for deciding if an idea is actually worth pursuing further.

As I mentioned, I’ve been using a small whiteboard. It’s common for software developers to have larger ones on cubicle or office walls nearby. Those are great too, especially if you’re visualizing complex UML architectures. The games I’ve been building are generally quite simple, so I haven’t focused much on code architecture. For that reason, a smaller whiteboard gets the job done. The biggest advantage of a small whiteboard comes from the fact that I’ve been working from different locations almost every day. It’s nice to have a whiteboard that is portable.

Prototypes

Early in development, new ideas need to be tested. This process can go anywhere from a simple drawings on a whiteboard (as mentioned earlier), to semi-interactive proof-of-concepts, to fully-featured demos that only need refactoring and better art before turning into production code. Which of these prototyping choices is needed should be determined on a case-by-case basis. Generally, the more likely it is that a feature will be very time-consuming or difficult to implement, the more complex your prototype should be.

Later in development, features that didn’t need prototypes to ensure that they weren’t blockers may still benefit from quick prototypes outside the game’s main codebase. When one of these features comes up as my next task, I’ll often create a new project in my IDE and play around with some ideas. This not only ensures that I don’t mess up any of my existing code (obviously, this can also be handled through version control rollbacks instead), but it also helps me focus on the single task at hand without all that other code to distract me. One possible benefit from this separate project is a cleaner API, in terms of reusability, because I’ll have a harder time tightly coupling this new code to the existing code in the main project.

For one game I built, a match-3 puzzle game, I made several prototypes to validate the gameplay. They led to some very important changes that improved the game mechanics quite a bit over time. It started with a whiteboard drawing that seemed to validate what, in my head, I envisioned to be a very fast-paced and fun game. However, the first functional prototype with interaction showed me that matches happened too often, and that made the game extremely easy and quite boring. I simplified the controls a bit in the next prototype, but I added a timer-based game mechanic that still kept the matches paced as quickly as before while speeding up other aspects of the game to ensure that the player had some challenges that required him or her keep up.

These changes I made in each prototype helped to make the game a little more fun. As pieces started fitting into place, I could discover other parts of the game that needed tweaking for each successive prototype. In the end, the game mechanics got more and more basic, but they focused strongly on what actually made the game fun to play. So far, this process of simplification in the prototype stage has helped me improve every one of my games as they moved from conceptualization to actual development.

Content Creation Tools

I have a wide variety of tools that I use to develop my games. For my first game, Chroma Circuit, I did all of my development in Flex Builder, and almost all the graphics are programmatic (other than some assets used in the main menus). That game had certain strict geometric requirements that made it difficult to build some of the game’s elements visually. Ultimately, I chose to organize the final code (which has several branches, for reasons that I’ll talk more about later) in such a way that it’s easily built with a short Ant script.

For my second game, Gridshock (still in development at the time of this writing), almost all the graphical assets were created using the vector tools in Flash CS4. I still wrote my code in a Flex Builder ActionScript project, though, since it provides a much better code editor. It’s worth noting that I tried using Powerflasher FDT for a while, but it didn’t quite fit my style of development. Still, I mention it because can provide a similar workflow in place of Flex Builder. For this game, I chose to compile the SWF in the Flash authoring tool instead of with the Flex SDK, but I could have embedded the assets in code and stuck with Flex Builder for all development-centric tasks instead. Mainly, I went with the Flash authoring tool as the compiler because had the urge to try a workflow based around a FLA file rather than only a document class. I can’t say that I encountered many disadvantages, other than switching windows more often to go between Flex Builder and Flash CS4, so I may try this workflow again with other games.

For audio editing, I’ve been using a combination of Apple’s Garage Band and the open source tool, Audacity. It’s worth noting that when I was a Windows user in another life, I enjoyed working with Adobe Audition a bit more, but Audacity has been good enough for me on my Mac. All of my sound effects are derived from royalty free sounds that I purchase for a small fee online, but most of them receive some tweaks. In fact, I’ve often made collections of related sounds derived from the same original audio file as a way to offer some better aural continuity in a single game.

Version Control

Of course, using a version control system is software development common sense, but for many folks who use their free time to create casual games or do any other type of development, it might be a forgotten detail. Allow me to highlight a couple notable reasons for considering a version control system for games.

For me, one of the biggest advantages of using version control for Flash games is related to sponsorships. If your game is popular with sponsors, you might get a primary sponsorship and one or more non-exclusive, site-locked sponsorships. This means multiple versions of the same game, and if you’re using version control, you’ll be able to manage these separate versions with branches. Need to make a change for one particular sponsor? Just edit the files in that version’s branch, and it won’t affect other sponsored versions. Need to make a change to the core game? Do it in the main branch, and merge those changes into the sponsor-specific branches as needed.

For any type of development you do in your free time, it might be a good opportunity to check out one of the various free version control systems you possibly haven’t used yet. Distributed systems like Git and Mercurial have been gaining in popularity recently, and many prominent open source projects have switched to them from centralized systems like CVS or Subversion. This may be a sign that the business world will switch eventually too, so it’s a smart move to begin exploring DVCS now, if you haven’t already (I personally haven’t yet, actually, but it’s on my list of things to do).

It’s worth noting that if you compile games (or any other type of project) with the Flash authoring tool, the binary nature of a FLA file makes it potentially difficult to use with version control systems, try to keep as many assets externalized as you can. Obviously, that includes all source code that can be put into class files, but maybe even images and sound files if they change often enough. Basically, ensure that changes analyzed (diffed) by the version control system are focused to the specific asset files and not on one giant centralized FLA file. This should help to keep your repository history from taking up massive amounts of space, and you’ll find it easier to rollback changes to specific assets while keeping others in their current state.

Conclusion

Again, I’m not trying to cover every detail of my daily development workflow, and probably went into more specific details in some areas than I did others. The process of explaining some things certainly helped me to better understand some of my new processes. It even helped me compare how I’ve been building games a bit more critically to my previous workflow with reusable components. Thanks for reading.