Inconsistent SceneManager semantics

I’ve noticed an inconsistency with how SceneManager handles integer scene indices, which is causing some problems for me. In my example, I want to know what scene comes after the currently-active scene in the build settings. I don’t want to load that scene, I just want to know what it is.

So, let’s say i’ve got the following scenes in build settings, with their associated indices (again in build settings):
A – 0
B – 1
C – 2
D – 3
I start the game in scene A, and let’s say it additively loads scene C*.* Note that right now, as far as SceneManager is concerned, GetSceneAt(0) means scene A, and GetSceneAt(1) means scene C.

Let’s say i want to get the scene that’s right after scene A in the build settings:

var sceneA = SceneManager.GetActiveScene();
var nextSceneHandle = SceneManager.GetSceneAt(sceneA.buildIndex + 1)
var nextSceneHandle = SceneManager.GetSceneAt(0 + 1);    // equivalent to above
var nextSceneHandle = SceneManager.GetSceneAt(1);    // equivalent to above

But since SceneManager.GetSceneAt(i) only looks in the currently loaded scenes, this will give me
nextSceneHandle = “scene index 1” = scene C
rather than “scene index 1” in the build settings which would = scene B.

However: if i did SceneManager.LoadScene(sceneA.buildIndex + 1), that would load scene B, because LoadScene(i) looks in the build settings, not in the current list of loaded scenes.

As far as I can tell, there’s no way for me to “Get…()” a scene from the build settings without loading it. Which is unfortunate, because I want to have some logic, at runtime, based on what scenes are added to the build settings.

@nickfourtimes1

Hi, and sorry if I sound bit simplistic, but is there a reason why you couldn’t just use baked data?

With SceneManager.sceneCountInBuildSettings it’s possible to get scene count in build settings but there doesn’t seem to be comparable command to SceneManager.GetSceneAt for build scenes.

So unless someone more knowledgeable has a better solution, why not just store the names and indices of your scenes, then use those runtime?

First – even though I do already use baked data in some scenes – I don’t want to have to re-bake everything for each incremental build I make. Between festivals, demos, playtests, debugging, &c., I’m building many different versions of the game, each with a slightly different setup. Instead of spending time architecting an editor tool generic enough to account for all possible variants, I’d rather rely on a system that already seems mostly-implemented in Unity. The SceneManager class obviously can address editor-build scenes (via LoadScene(i)), so why not just rely on this tool?

Second, there’s the issue of the semantic inconsistency.

var index = 1;
var sceneA = SceneManager.LoadScene(index);
var sceneB = SceneManager.GetSceneAt(index);

There’s nothing in the above code to suggest that sceneA will differ from sceneB, which, currently, they do. Only one of SceneManager’s methods (LoadScene(i)) has access to editor-build settings; none of the others do. This is undocumented (or at least poorly so), and could be improved by either a) better naming conventions on SceneManager’s methods (LoadSceneInBuild() and/or GetLoadedSceneAt(), e.g.), or b) providing more functionality to SceneManager (i.e., the ability to refer to scenes in the build).

“Only one of SceneManager’s methods (LoadScene(i)) has access to editor-build settings; none of the others do”

Yep, I’m aware of that, it’s mentioned in manual (“Index of the scene in the Build Settings to load” or “Name of the scene to load.”).

I’m not sure exactly what you mean by “There’s nothing in the above code to suggest that sceneA will differ from sceneB” but like manual mentions, SceneManager.GetSceneAt gets scenes inside scenemanager, while loadscene gets scenes from build scene list, that how it works AFAIK.

“providing more functionality to SceneManager”

Sounds like a good idea.

I’m pretty sure this doesn’t help you but if someone else is interested:
http://davikingcode.com/blog/retrieving-the-names-of-your-scenes-at-runtime-with-unity/

That’s the workaround I’m using in the meantime for the final build of the game, though I’d still argue that the method nomenclature needs to be more descriptive and/or the implementation of SceneManager should be more thorough – at the moment it’s just a frustrating and arbitrary limitation.

1 Like

I agree this is stupid

for (int i = 0; i < SceneManager.sceneCountInBuildSettings; i++) {
if (SceneManager.GetSceneAt(i).name.EndsWith …etc

Only to find out that yeh… GetSceneAt is only for the scenes that are loaded, totally fine with that… but where the hell is the function that can get scene name info etc from unloaded scenes that are included the build of settings of a game… without annoying workarounds.