How to Manage Scene References in Unity with Scriptable Objects

Bridge the gap between Scenes and Strings with SceneObjects.

·

2 min read

In Unity, referencing scenes at runtime is a surprisingly clumsy task. Scenes are called by name, provided as a string, which opens many doors for typo-related bugs and lacks flexibility if you happen to want to change their names and reorganize them.

Unfortunately, the way scenes work is different for the editor and the build. In the editor, scenes are scene assets, a kind of YAML file filled with GUIDs and setting overrides. In the build, they are converted into a special binary format and no longer exist separately. To load a scene, one must use the string name of the scene.

SceneManager.LoadScene("SceneName");

The problem with this is that, as a string, the name is hardcoded (or stored as a serialized string set in the inspector). Any changes to the scene reference, even if just renaming it, must be manually retyped at every point it appears in the codebase. This introduces a lot of opportunities for bugs.

The SceneObject

The SceneObject scriptable object solves these problems by wrapping the scene reference in an object. In the editor, a scene asset reference can be set in the inspector and the SceneObject automatically stores the name as a string when the object is validated. At runtime, the scene can be acquired by calling sceneObject.Scene.

public class SceneObject : ScriptableObject
{
    ///Implicitly converts a scene object into a Scene reference.
    public static implicit operator Scene(SceneObject self)
    {
        return self.Scene;
    }
        /// Implicitly converts a scene object to a string containing the scene name.
    public static implicit operator string(SceneObject self)
    {
        return self.sceneName;
    }
    // -------------------------------------------------------------
    public string sceneName;
    public Scene Scene { get => SceneManager.GetSceneByName(sceneName); }

#if UNITY_EDITOR
    public UnityEditor.SceneAsset sceneAsset;
    // -------------------------------------------------------------

    public void OnValidate()
    {
        sceneName = sceneAsset.name;
    }
#endif

}

This SceneObject has implicit casting to both a string and a scene, allowing it to be used in almost any scene-calling function as-is, converting to either a scene or a string depending on the function.

Conclusion

Scene references in Unity can be annoying to work with and prone to typos. By wrapping the scene reference in our own custom object, we can make working with them easier, and make changing or reorganizing them less of a headache later in the project.

Did you find this article valuable?

Support Bear Evans by becoming a sponsor. Any amount is appreciated!