A peek into the beautiful low poly level design, a sketch of the game’s intro, and more.
So enjoy this weeks content.
Video
Both a technical peek and a story peek this time: I am demonstrating the use of additive loading of the scenes in the game engine, and I use parts of the intro scene (the sketch version) to show this functionality off.
Low poly level design
Here is a screenshot of the work-in-progress on one of the city themed levels:

This shows the city with the low poly diorama vibe that I wanted. Here you see it in the evening sun. The lore is as follows: “The gnomes in the city are more crazy than the earlier gnomes, not only lost but also possessed by the worldly goods they found here.” This lore will be referenced to before the city levels start with a hand drawn introduction.
I am working with a few different artists currently. This design is from Syoma. He really nails the diorama vibe combined with the low poly techniques I want to use.
The game is currently planned to launch with 4 themes and 3 levels per theme, with the city levels being the largest (and last).
Introduction scenes
Speaking of the hand drawn introduction scenes. In the video of this blog you could see parts of the main introduction we are working on. Its a cartoon combined with some parallax effects.
For now its a sketch only, so we can see if it works and then move on to draw the final images and color them.
There will be 5 longer introductions in the story flow, and a few smaller ones that unlock if you achieve specific objectives.
These cartoons are from a official cartoonist, so the game is already worth playing for getting to see the cartoons! See his other work on meinder.nl.
Additive scene loading
So on the ‘additive scene loading’ technique. It took me a few attempts to get it working, but I have additive scene loading in my game now.
I want to share with you how I solved this. Especially for the technical people that read my blogs. And I know that a lot of you, my readers, are technical minded people. So here you have my take on this!
So what was the problem, the promise, the solution and lessons learned?
The problem
Unity is build around scenes. See it as a stand alone level that contains all moving parts needed for you as a gamer to ‘play’. So its a combination of models, scripts, UI and some ‘flow controlling’ to get to other levels/scenes.
I have created a few games already. And every time after a certain time into the development process, I get the need in my game to automate going from scene to scene. Most of the times I create a data object somewhere to record what level is tied to what scene (file), and then use a manager of some kind to load this level on demand. This manager also knows a bit about menu’s and other places so it can direct you there. But it is based around ‘one scene life at any time’ and thus needs to fully unload the current scene and then load the next one.
After a while another problem starts to appear: when the scene/level is loaded, there is a certain order in which you want to start all objects and UI objects because they are often relying on each other for state and updates. I call this a ‘loading sequence’. (And it applies also for level unloading). Unity has some tools for this, its called the ‘object lifetime cycle’. But just using the awake, start and the other object lifetimes in Unity is very limiting. Especially if you want to do some save state loading, or dynamic object discovery, you then need more control in the loading process. One approach would be to have object specific signals that only act on the loading/unloading, but creating your own signals and then managing what signal to hook on is quickly getting a mess, especially if you want it to work while in the editor as well as in the official build. And don’t add objects to it that have a lifetime that exceeds the level/scene (like ScriptableObjects) because this will make your game explode into a fountain of very hard to track bugs.
And if this isn’t enough, I tend to get into re-usability issues very quickly. I want some objects, like the UI, on all scenes of a specific type. For instance, levels need the level UI. Or I want a Debug UI to load and be always available. Or I want a loading screen to be visible while unloading the old scene and loading the new scene. And like I said, scenes fully unload at the end. So I don’t want these specific UI elements to unload. And yes I know this can be manually solved in Unity with a ‘do not destroy’ hack. But then you have to account for certain objects being around after the lifetime of a scene and not keeping ties to the (then unloaded) scene and cause problems… so in the end you need to manage this (proper tying and untying) anyway, so why not use proper patterns and structures that make that everything can be loaded/unloaded on demand?
The promise
So that is where you come to ‘additive scene loading’. This additive scene loading is often advertised as a best practice if you want the most in-game object lifetime control and also stay true to the Unity editor patterns.
Additive scene loading comes with a few benefits. And you don’t need to use all of them, but its very easy to use these if you have these additive scenes working:
- Seamless level transitions (without loading screens).
- Much more easy to manage asynchronous level loading.
- Improved UI editor flow by not having the irritating UI that gets in the way while working on the levels themselves.
- Less massive scenes and thus way less chance for merge conflicts while working on scenes.
- Better decoupling of your code in general, because additive scenes work on a proper event subscribe/unsubscribe system, and that pattern also gives you a proven reliable decoupling mechanism that you can then also use on other parts of your codebase.
The solution
A scene can very easily be additive loaded by just stating to Unity ‘load this scene additive’.
But for this to work seamlessly you have to implement some sort of state machine to track whats happening. Previously you knew where you are at by just looking at the scene’s name. But now you need an overarching state machine that keeps track of where you are and where you want to go to.
I added a few additional layers on top of it to also address the other issues I faced:
- A level sequence object that I can ask: ‘what are the available scenes for this game’. I have levels, intro shots, and 1 map. And fill this sequence object with directions on whats available in the editor with custom tools.
- A level transition object that I can ask: ‘go to the next story scene’. Or ‘oneshot this level and then return to the map’. (It uses the level sequence combined with savestate to determine what’s unlocked and where the player is with his story unlock progression)
- A state machine that consists of a few parts. (all custom code, not the Unity state machines)
- The state machine itself. This keeps track of the current state it is in, initiates transitions, and keeps actions atomic. Uses IEnumerator to make it asynchronous (well, that is Unity-style async sadly, not .Net async).
- A state class model. 1 class for a start-game state, 1 class for a level state, 1 class for an intro shot state, 1 class for a map state, 1 class for a game-exit state. Each state has 2 main functions ‘`RunOnEntryLogic(transition info)’ and ‘RunOnExitLogic(transition info)’, both IEnumerator to support chaining actions inside the logic and to wait for stuff to happen. Each model has its own series of events on it so you can fine-tune the specific amount of events per state. These events are called in the logic functions with yields to keep the ticks flowing in Unity and behave non-blocking.
- A static class with instances of each one of the a fore mentioned classes. So scripts can reference these from anywhere to hook themselves up to the events of their liking.
- A transition object. Very simplistic, just to get basic info like ‘Start level 1.1’ or ‘Start map’ to the states.
- A few smartly placed calls to ‘ensure loading screen’ and ‘hide loading screen’ and ‘pause game’ and ‘unpause game’ in the states. To make it possible to prepare stuff without the user seeing artifacts of this preparation.
- A scene specific for the state machine. There is only 1 script on this scene, and it initiates state transitions. This scene is always around.
- A startup sequence script. It knows what scenes to additive load. And triggers the state machine.
- An editor specific version of the a fore mentioned startup sequence, to speed up the development process. This one primes the scene as if you jumped right to this point in the game (and thus loads all needed additive scenes on play and sets the state machine to the correct state).
On the additive UI scenes: I have a bunch of additive scenes that are always on, like a debug overlay. Most of them look for certain events and/or state (transitions) to enable/disable parts of itself. (So its a reactive system, much easier to maintain) And most of the objects on these additive scenes have scripts that use OnEnable and OnDisable to hook and unhook events, so that references are always only on ‘active and life scenes’.
Lessons learned
Okay, what did I learn from this whole escapade? Well.. that it works like a charm. You can do a lot of powerful things with it:
- The state machine combined with the startup sequence scripts is sooo helpful. I now can be sure events are fired in the right order with the right systems loaded and prepared to the right state. Even with no difference between the editor and the official build.
- It looks cool. In the editor. With all these scenes loading and unloading on demand. And it all runs without synchronous code that takes ages to complete and prevent certain parts of the code to continue.
- I have a few ScriptableObjects for singleton behaviors and better decoupling, and normally you dont want this because these are hard to keep them nog bugging due to their different lifetimes. But now these can be hooked up perfectly to state transitions to give them better boundaries, but at the same time not mess up the decoupling.
- The class based static scene setup is very easy to use and maintain. And to understand. And thus to work with, reason about, and improve upon. That’s worth the downsides of this system for me.
And some ‘less than optimal’ things I encountered:
- This whole class based state system has a major downside. Being that its not using Unity’s preferred patterns and components. And it still is the service locator antipattern because of all the static singletons.
- The IEnumerator is a bit of a pain to work with. Especially if you pause your game by setting Time.timeScale = 0, you then don’t want to use yield functions that wait for the next realtime tick to happen. You want to use WaitForSecondsRealtime instead.
- And another thing on the IEnumerator: it needs to be started as a Coroutine on a script that is kept around, even when unloading stuff. So you don’t want to call it as a Coroutine from the scene that is being unloaded, but instead call a script on a scene that will be around that on its turn calls the Coroutine. Thats why I have a dedicated state machine scene now that first to be alive on start, and then manages the state (and scene) transitions from there.
I have spend hours and hours locating a bug because of this. I wanted to transition away from the starting scene but the code just stopped executing at a certain point in time. Until I found out that the Coroutine is bound to lifetime of the MonoBehaviour, and I did fire it from within the starting scene.
Leave a Reply