Modern image processing software like Photoshop have this concept called “layers” in which the user can compartmentalize different parts of the whole image using this construct. Scenes in Unity can also be thought of as layers. Each can be developed separately but they can be combined together to form the whole game. Over the years of using Unity, I have been using this concept to develop my games.

Engine design wise, I think “scene” is a wrong term. It’s because a scene denotes something visual, something you can see, or something tangible. Intuitively, a user would think that a scene is for visible objects with their physics settings. Essentially though, a scene is a container of GameObjects. In this sense, a scene could contain only non visible stuff like game managers and data managers. A scene could contain only cameras, or only UI. What this means is you can make separate scenes for your game world, game logic, cameras, and various UI panels. When the game is run, you can additively load these scenes together which collectively makes up the whole game.

The Basics

Let’s say you have two scenes – “GameWorld” and “GameHud”. It’s a good idea to make another scene which is responsible for loading the other scenes additively. Usually this is called the “Main” or “Startup” scene. Whenever you want to run the game, you play this Main scene instead. This scene has a component that looks like this:

using UnityEngine.SceneManagement; ... // Other using statements class Main : MonoBehaviour { void Awake() { LoadSceneAdditively("GameWorld"); LoadSceneAdditively("GameHud"); } private static void LoadSceneAdditively(string sceneName) { SceneManager.LoadScene(sceneName, LoadSceneMode.Additive); } }

Why do it this way?

I have three main reasons – better organization, better work delegation, improves maintainability.

Better Organization

For example, I always make a separate scene for the system that handle audio. I have a separate scene for the system that handles persistence (saving and loading). Game static data management is contained in its separate scene. I can manage the different domains of game elements in their respective scene. Like in Academia, each handling of character types is its own scene.

Sometimes, it’s reasonable to put usage of third party software in a separate scene. If the game is level based (Level 1, Level 2, etc), each level can be a separate scene. Each UI panel or screen can be its own scene. A game feature can be its own scene. You open up many ways to organize your game.

Better Work Delegation

Now that the game is structured into multiple scenes, it becomes easier to assign work to team mates. You can assign someone to work on particular scenes or tell them to add a new scene (if it’s a new feature). An obvious example is to distribute work among different UI panels or screens. Doing it this way also reduces collaboration conflict. You can design your development such that artists and designers edit only certain scenes while programmers also work on their logic only scenes. It’s also now easier to know who’s fault it is when the game breaks. Just ask who owns the scene.

Improves Maintainability

Maintainability is very important to me. It’s that one thing that a software project has that allows it to be shipped. By separating domains in different scenes, the areas of where to fix or where to update becomes more clear. A new feature now means a new scene. Scenes that work well can be forgotten. This means more space for your mind to focus on more important things. You can also think of scenes as another way to refactor your game. You can split up a big scene or merge smaller scenes.

How do you render different scenes into one display?

You use multiple cameras. You can check this awesome post. This is the reason why I maintain cameras in a separate scene. In every game, I maintain at least two cameras, one for the game world, the other for UI.

How do scenes communicate?

There are lots of ways to do this. Personally, I prefer something that does not require a hard reference of some class or component. We use a signal system to signal something and interested parties will then do something. Kind of like a glorified observer pattern. We also use a query system. It’s like a signal system, but it returns a value. There are times when a program in a scene requires a value from another scene. We use this query system to get that value without requiring the reference of the provider. I’d like to delve into details, but this post is getting longer. So maybe in another post.

Taking it Further

Instead of hardcoding the scenes to load like I showed in the Basics part, you can make something like an XML or JSON config for this. Every time there’s a new scene to load, you just add that scene to this file.

In our system, I designed something called “Load Profiles”. Basically, we maintain different profiles of loading scenes. For example, there’s a profile for loading the complete game, then there’s another profile that loads the game directly to gameplay which is used for testing. This can also be used to load different scenes for different platforms.

You can design different patterns on how you load your scenes depending on your needs. This is it for now. See you next time.