Unity is a great ‘blank canvas’ engine for creating applications of just about any kind. However it’s not the most intuitive when you are starting out just ‘how’ you go about structuring anything. The very open-ended / extensible nature of the engine means that just about every single studio in the world has a different way of approaching their game’s structure and organization.
In this post, I’m going to share some of the things that I’ve figured out the hard way over a decade of working with Unity, explain some of the reasons how and why you might want to use similar techniques for your own project.
Bootstrap / Startup Scene
If you look at just about every Unity example project / template on the asset store, a common limitation / issue I have with them is that they assume that all of the ‘action’ happens within a single scene - there is no macro ‘game logic’ that handles things like player profiles, inventory, save states etc that lives across the entire game’s lifecycle.
One advantage of having each scene be ‘self-contained’ is that you don’t need to worry about anything that exists outside of the scene. This makes testing your game easy - you just load a scene and hit play!
The main disadvantage comes when you are doing more real-world production examples, where you need log into a server, download info about the player from a platform like Steam and more sophisticated behaviours.
This is where the concept of a bootstrap scene comes in.
What is a Bootstrap?
To borrow from the excellent Heathen Knowledge base (which you absolutely should check out!):
Bootstrap Noun COMPUTING a technique of loading a program into a computer by means of a few initial instructions which enable the introduction of the rest of the program from an input device.
Verb COMPUTING fuller form of boot. "boot" such as to "boot" your PC is a short form of "bootstrap"
A Bootstrap scene is where we define a simple scene containing only the system level objects of our game. The purpose is to initialize the core systems of a game, to validate the environment and systems are ready to load the game and then to load the main game.
In fact, they have an awesome tutorial video describing the process much better than I can:
Now that you’ve watched that you hopefully understand the ‘why’ we want a bootstrap. I also agree with pretty much ALL of the other points that Heathen makes on their ‘bootstrap’ knowledge base page regarding multiple scenes, why you want them and otherwise.
Bootstrapping in Dystopia Punk
For all of the work I do in Unity I use 2 key concepts to help with the idea of a bootstrap:
Bootstrap Spawner
Service Locator
I’ll describe both below.
SpawnOnAwake()
The first is a very simple script simply called ‘SpawnOnAwake()’ - what this does is wait for the Unity magic Awake() method that is called when a scene is loaded and simply instantiates / spawns any number of prefab game objects that you specify.
using System.Collections; | |
using System.Collections.Generic; | |
using UnityEngine; | |
namespace PixelWizards.GameSystem.Controllers | |
{ | |
/// <summary> | |
/// Spawns any number of prefabs on Awake() when the scene loads | |
/// </summary> | |
public class SpawnOnAwake : MonoBehaviour | |
{ | |
public List<GameObject> spawners = new List<GameObject>(); | |
/// <summary> | |
/// Awake is the first thing called, spawn all of the items we need | |
/// </summary> | |
void Awake() | |
{ | |
foreach (var spawn in spawners) | |
{ | |
Instantiate(spawn, Vector3.zero, Quaternion.identity); | |
} | |
} | |
} | |
} |
As you can see, this script is about as simple as they come. In the Unity Editor you simply attach it to an empty gameobject and add whatever prefabs that you want to spawn into the list on the inspector:
The image above is directly from Dystopia Punk - it has 5 separate prefabs that it spawns into the scene when the game starts, 2 debug prefabs (Debugging Essentials and Advanced FPS Counter), 2 Rewired prefabs (the event system & actual input manager) plus a custom Service Manager, which I’ll explain below - it is the second key component of how I handle just about everything in Unity.
Before I jump into that however, I’ll just call out the 2 debug packages, as I forgot to mention them in my prior post about ‘useful Unity stuff’.
Debugging Essentials is a fantastic set of tools that provides a debug console, a runtime hierarchy window + inspector and a great HTML Debug log formatter. You can use it instead of writing Debug.Log and view the output directly within your game - and it’s infinitely faster than the default Debug.Log as well (which can literally slow your game down at runtime due to the way it writes the logs to the file on disk).
The runtime Hierarchy & Inspector is fantastic - you can view what is loaded in a scene and even change parameter values live while your game is running! It’s very useful to troubleshoot what’s going on at runtime in the editor AND in builds
The HTML debug output is fantastic as well - much more readable than trying to read the default Unity debug output and also includes timing information for when a given event happened, which can be useful as well.
Advanced FPS Counter - there are dozens of different framerate tools on the Asset Store, but this just happens to be the one I’m using at the moment. It gives me a nice in-game FPS counter (you can see it in some of the videos I shared previously) and ‘just works’ - you drop it into a scene and voila. Another similar tool that is great is Graphy, which also happens to be free.
Service Manager / Service Locator Pattern
The second major technique that I use in my Unity development is a software pattern called the ‘Service Locator’. You can think of a service locator as a way to link components at runtime. Another similar technique is ‘dependency injection’. I’ve included a link to the Wikipedia page if you want to read more about both.
Other common patterns that you will see a lot in Unity games are Singletons and Static methods. I’ll get into each of these and how I approach handling similar challenges next time!
Until then, thanks for reading and poke me on Mastodon if you like how this is going so far!