Unity3D 5.3 introduced a new, powerful scene management system that had been in the works for a good long while. Its new SceneManager class is powerful, supports additive scene loading, and even on-the-fly scene creation, identification and, well, management. We haven’t used it once.

Don’t mistake this for criticism of the system itself. As we will discuss further down this blog post, it’s a well-implemented system that has many advantages. Sadly, if you’re developing on mobiles, or already have your own workflow set up for loading and saving game levels, it’s not going to be as useful to you. And you shouldn’t feel bad about it.

After reading the new SceneManager documentation, and marvelling at its shiny, powerful new feature set, we felt kind of silly for not using it. So we tried, but it just kept getting in the way. The new system is great, and really does a fantastic job in allowing you to merge, track and manage multiple scenes. But we just couldn’t wrap our heads around it. It made us feel bad. If you’re in that situation too, this post is for you: don’t feel bad about not using A load of scenes in your game. You’re not the only one.

All Deep Horizon levels are prefabs whose interactive objects are instantiated at load time.

The main issue we had with the SceneManager was performance on mobile devices, and garbage collection.

Apologies for any heart attacks that title may have caused mobile developers. We didn’t mean to terrify you. It’s OK to come out from under your desks now. Garbage collection is what happens when you destroy stuff, and let your code wonder what to do with all those holes in its neatly-arranged memory stacks.

The solution, typically, is to freeze the heck out of your game, stutter like a shy teenager at a top model convention, and disrupt all kinds of gameplay systems because it suddenly has to clean up right there and then, no matter what’s happening with the rest of the system.

Avoiding the terrible performance loss that random garbage collection triggers is one of the main endeavours in mobile game optimisation. In order to avoid it, we pool objects, reuse meshes and try to instance as much stuff as possible. Using the SceneManager to change a level means that you give up all that control to a system that, once it deletes a whole bunch of objects, will most likely trigger garbage collection.

Now, sure, you can structure your scenes and code in a way that neatly cleans everything up, but that then means you’ll be basically managing each object within the scene yourself. And if you’re going to do that, why bother doing it through a separate system?

If you’re going to end up manually initialising, operating and cleaning up every single object inside your scenes, stick them in a prefab instead, and load that. You’ll save yourself the trouble of learning a new API.

Unless you’re developing a more graphically refined product that relies on light mapping, scene-based colour and fog settings and other specific, AAA-like features, you could potentially save yourself a lot of hassle by bypassing the SceneManager entirely.

Pulses Academy levels have no tiles or architecture, so we just baked the enemy sequences for each level into JSON strings.

All our games so far have relatively mature game engines, and usually build game levels dynamically at runtime (more or less) from stored json files. Whether it’s a tile-based level for Deep Horizon, or a dynamically generated set of floors for Salvage Heroes, or even one of the designed boards from Pulses, our workflow starts from a data set that gets turned into a level.

Nearly every game object except the background layers is instantiated once by a pooling system, and then is reused dozens (or hundreds, or thousands) of times by being set, reset, disabled, and stored again. When you get to a new level, we simply clean up the existing objects, package them away and store them in a pool. Then, the new level data is loaded, and out come the objects again (tiles, enemies, pickups and so on).

Everything happens in the single game scene where every game component is held. Everything is instantiated at runtime inside that scene. If garbage collection ever happens, it’s because we didn’t do our job properly. Admittedly, we’re in the indie sphere and don’t play around with large meshes, terrains and other graphically intensive objects, and if your needs are more elaborate, what we do may not work for you.

Unity3D isn’t special because of its toolset, which is coming along quite nicely, but because of its open-ended workflow that lets you use what you like, and get on with your life if you don’t like the way the engine does something. In our case, the performance and complications to the existing workflow we developed over the last half dozen games simply meant that SceneManager just didn’t work out.