Saturday, 29 June 2013

Default Anatomy of a Unity Application

So, you started a new project in Unity. You added your first game objects and scripted their behaviour. Do you think that's it? Your game is ready to run? Well then, hold your horses. There are several core objects you would find in almost every application. And the chances are you will most likely need all of them.

When you create a scene, there's already a camera object – the Main Camera. Without it, you would only see a black screen.

Then there's the GameController – a class that you will write yourself, although it may be named differently. Sooner or later you'll need to keep a global state somewhere – enemies killed, matches won, levels explored... That would be your GameController. Sure, it may be composed of different parts – Stats, Preferences, Progress, Inventory, etc. – but it's a good practice to keep them under one parent object (or implement them as scripts attached to that parent GameObject in some cases). It becomes increasingly useful if you add another scene. The GameController doesn't die with the scene; it exists for the whole duration of the application (i.e. it should be marked with DontDestroyOnLoad()). That also means that the GameObjects attached to it are preserved as well. So if you want to keep anything around at all times, you can (and should) simply attach it to the GameController or any of its children. It might not be possible in rare cases (when the transformation of a persistent object depends on an object that will be destroyed), but otherwise it is a sound solution.

There's a problem, however, with the not destroyable objects in general. You can't just put them into a scene as regular. If you had multiple scenes and switched between them, the persistent objects would duplicate. You could put them into the first scene, which would be loaded on start-up and then never crossed again, and it would work in the final game. During development though, you would often run scenes at random and they would be missing the crucial information that's supposed to always be there. The only solution is to introduce a helper object that will always die with the scene. Upon initialisation it will check if the GameController is present, and if not, it will create it (from a prefab). We can call this watcher GameLauncher and put the global logic that doesn't apply outside the scene under it.

One of such global objects could be GUI. UnityGUI is entirely scripted. That means we can create a number of scripts, one script for each screen, for example, and put them virtually anywhere. But where does it make the most sense? Since we can have many screens, it's certainly more practical to dedicate a separate GameObject for them than to “hide” them in random existing objects. I've seen people attach the scripts to the main camera. It's one possibility. Still, there could be multiple cameras in the scene, they could be nested in other objects – it could become cumbersome to locate a script. Another option is to leave the GUI object freely in the scene. Although, if there were many independent game objects already, it would only add to the clutter. Also, there could be screens available through the whole application, such as pause menu, and the screens specific to a scene, such as HUD. We could signify the difference by attaching one GUI object to the GameController and another to the GameLauncher, which are the pillars that will not move.

When everything else is in place, you'll need to save and load your game state. So there would be a SaveManager, which Unity doesn't provide and which you'll have to implement yourself, too. This is a huge topic and I plan to write more on it later.

No comments:

Post a Comment