Unity apps are structured very strangely. They’re a lot different than Flash or standalone apps and definitely take some time to get used to. Today’s article is an introduction to how a Unity app’s code is structured from the perspective of a Flash developer. It should give a basic understanding of where your code goes and how the basic architecture of a Unity app looks.

To recap, a Flash app starts with a Stage. It may also have one or more Stage3D and StageVideo in more recent versions, but the Stage is always there as a good basis for comparison. On that Stage is a “root” Sprite. If you’re compiling from pure code, this is the .as file that you pass to mxmlc:

mxmlc MyApp.as

That command will yield MyApp.swf with a root Sprite that is an instance of the MyApp class found in MyApp.as:

package
{
	import flash.display.Sprite;
 
	public class MyApp extends Sprite
	{
		public function MyApp()
		{
		}
	}
}

The constructor of the MyApp class is called when the root Sprite is created and added to the Stage. This class then controls all of the app from its constructor and any events it chooses to listen to. These typically include Event.ENTER_FRAME and TimerEvent.TIMER but may include others like Event.VIDEO_FRAME or Event.RENDER.

The app’s “main loop” is typically formed by successive calls to the function handling Event.ENTER_FRAME or TimerEvent.TIMER events. A mass of code is called from these event handlers to handle all of the app’s logic. In the case of a game, this may include input handling, display rendering, sound playback, network communications, file I/O, and so forth.

If the app isn’t compiled from a single .as file but rather built by Flash Professional, a “document class” will serve the same purpose as the “root” Sprite. The app’s logic may be much more spread out though. This is because ActionScript may be attached directly to entities on the timeline. For example, a small script may be added to stop an animation from looping by adding a simple stop(); on the last frame of the timeline.

In this latter case, there’s no need to set up a “main loop” based on Event.ENTER_FRAME or TimerEvent.TIMER since Flash Professional allows a more graphical, timeline-based approach to writing the app’s code. Some find this approach to programming extremely intuitive while others find it repulsive. Whatever your opinion, it’s a very common way that Flash apps are built.

With that overview of Flash architecture in mind, let’s discuss Unity. Apps that are built on Unity always use the Unity Editor. This is the graphical tool that allows us to build what Unity calls “scenes”. Each scene primarily consists of a hierarchy of GameObject instances. Each GameObject has Component instances attached to it. Unity’s scenes are somewhat like Flash’s stage and Unity’s GameObject is somewhat like Flash’s DisplayObject. There isn’t a real equivalent to Unity’s Component in Flash.

One of the biggest differences between Flash and Unity programming is that Unity has no concept that is like a “root” Sprite or “document class”. All of your code is attached directly to a GameObject in the scene. The way this is done is via a class called MonoBehaviour. When you want to write code that attaches to a GameObject, you don’t extend GameObject like you would extend DisplayObject in Flash. Instead, you extend MonoBehaviour which in turn extends Component. This allows your class to be instantiated and then attached to the GameObject. Here’s a trivial MonoBehaviour:

using UnityEngine;
 
public class MyScript : MonoBehaviour
{
}

Instead of events like Event.ENTER_FRAME and TimerEvent.TIMER driving the “main loop” of a whole application, each MonoBehaviour listens to its own events. Instead of Flash’s EventDispatcher system, “magic” function naming is used. Here are just a couple of them:

using UnityEngine;
 
public class MyScript : MonoBehaviour
{
	public void Start()
	{
		// ... script started
	}
 
	public void Update()
	{
		// ... every frame
	}
}

I won’t go into the full litany of events available to MonoBehaviour classes in this article, but they’ll be discussed in upcoming articles. In the meantime, the Unity docs cover them pretty well.

This lack of a “root” Sprite or “document class” has a very large impact on application structure. Instead of a single “root” that “holds” all of the main components or engines of the game, the system is decentralized. Each MonoBehaviour is a peer of each other MonoBehaviour with none in a “master” role. Think of the system more like a graph than a tree.

When faced with this unusual architecture, many developers are tempted to—or even implement—a system where there is only a single GameObject with a single MonoBehaviour attached to it. It’s usually called Main.cs, Root.cs, App.cs, or Game.cs and serves just like the MyApp.as above. This is a valid way to architect a Unity app, but has plenty of drawbacks of its own. For example, the Unity event system’s “magic” functions don’t allow for easy listening to events on another GameObject.

If you choose to use a system with many decentralized MonoBehaviour instances rather than the “root” GameObject approach, you’ll find a variety of other challenges to contend with. Among these are difficulties in Update and Start event ordering and poor support for RAII. This is not to say that all Unity apps are necessarily “unclean” or a “hack”, but rather that they, like Flash, feature their own unique challenges which must be overcome by clever, well thought out application architecture.

This has been just a high-level overview of both platform’s app structures and how they compare. There are many details (e.g. scenes in Flash, C++ code in Unity) that haven’t been covered here, but these basics should cover most apps at least until the point where they start using advanced functionality like Flash ANEs or Unity’s platform-specific plugins.

To recap, here’s a handy table showing the rough equivalences between Flash and Unity app architectures:

Concept Flash Unity
App Container Stage Scene
Main Building Block DisplayObject GameObject
Main App Controller “root” Sprite/”document class” n/a
Script Attachments Timeline scripts in Flash Pro MonoBehaviour

Spot a bug? Have a question or suggestion? Post a comment!