So recently got this idea. Instead of having multiple scenes and a “Master Scene”, there would only be a single scene and all “Scenes” (now GameObjects) would live in this single scene.
The hierarchy would look something like this:
Main Camera
My Singleton Object 1
Level 1
Enemy 1
Enemy 2
Treasure Chest
500 Gold
Trap
Hidden Enemy
Level 2
Enemy 1
Level 3
etc.
“Scenes” could be instantiated (since they are GameObjects) and they could be disabled / destroyed as needed to free up memory.
Cross-scene referencing would be a lot easier.
It would be a lot easier to set up the scene with common objects like Camera or Music Player, etc.
I don’t see any real advantage. You can do the “my whole game is a single scene” thing by having a starting scene and then make use of additive scenes.
You can load scenes additively (and destroy those additive scenes when they’re done), and you can load them up asynchronously on background threads. These scenes could contain game levels, or just some music or UI elements, or a new type of enemy to fight. So … I would stick with the scene way of doing it unless there is something you simply cannot accomplish that way.
Now, if you want to keep your game organized by instantiating themed groups of game objects based on a script or scriptable object, that seems reasonable to me. Like, you could have a script or scriptable object for each level that dictates what enemies are spawned, how many of them, what their traits are, and so on.
I think that’s fairly commonly done, with the exception being that if you want to use light baking or GI, or just environments you’ve created by hand in the editor, you’ll still want to have scenery that is in … scenes … that you load up when needed. If your game environment is procedural and you aren’t using those sorts of features, you could get by without loading any scenes except the starting scene.
Well even with additive scenes you have to make sure all the necessary objects are there and in the right quantities. The AudioListener added by default on the Main Camera causes issue if it’s there is more or less than 1 in the scene.
This would be more convoluted than anything. You’re having the right thought processes though.
Additive scene loading isn’t hard (it’s just an option on the load scene call) and even gives you a place on that call to hook into / observe if it’s done easily (you make an AsyncLoad object and then you use it, and it has that info).
For a small game Unity will load scenes so fast at first don’t worry about that, just use the additive loading alone.
This is basically what we do - but we did it that way simply because of the nature of how RTS games work. You use a menu to set up a match and then load a map and play. Since we shipped a built-in Map Editor (which is its own scene) our maps are data files and not scenes. Our hierarchy is basically:
World Parent
— Structures
------ …
— Terrain
------ …
— Units
------ …
This makes it straightforward to “unload” a map and head back to the menu after the match is over.
Our terrain system is essentially a series of tile prefabs that snap together to form the map. They have a simple box collider that represents the “floor”. Edge pieces have vertical box colliders that units use as detection helpers so they don’t path over gaps in the map.
Buildings are made up of two prefabs - one for the exterior and one for the interior. These get placed on top of each other and toggled on/off when friendly units enter/exit the building. We have a custom shader that does height-based vertex transparency on the exterior model when in interior mode so players still get a sense of what the outside structure looks like. Fire points (allow interior units to shoot out windows at exterior units) are child empties of the interior prefab.
Map props go in their own hierarchy as well and are either interior or exterior props. Interior props have to be “owned” by a building (placed within the bounds of the building’s colliders) so they can be turned on and off as well. Cover points are placed as child empties in each prop and the facing of the empty is used to determine unit facing when in the point and which way the point considers “forward” to mathematically determine flanking etc. Props use standard colliders to describe their shape.
So we load terrain, then buildings, then props. Next we manually render reflection probes (turning objects on/off to prevent artifacts). Then we build the exterior navigation graph as a grid by just starting in one corner of the map and shooting rays at the terrain at regular intervals. Once we have our grid we sphere cast each point to check for nearby colliders and set the maximum radius of that point to that distance. This way big vehicles can’t drive down narrow alleyways and units maintain some distance from walls etc. Once that’s done we do a similar process for interior navigation graphs for each building; only we use the exterior collider(s) of the building to determine the extents of the grid. Basically, the exterior colliders determine the size and shape of the building and the interior colliders describe any interior walls or places that are otherwise not navigable.
All of the prefabs are just loaded via Instantiate and parented to the appropriate empty and all those empties are parented to WorldParent.
Once all of that is finished we place the player’s camera at their starting position, spawn their starting units, drop the loading screen, and turn all the controls and ingame UI on.
That was long-winded. Was there something else you were specifically curious about?