Search Unity

Feedback SceneAsset is terrible

Discussion in 'Editor & General Support' started by fr0zer, Dec 29, 2023.

  1. fr0zer

    fr0zer

    Joined:
    Apr 22, 2018
    Posts:
    3
    The SceneAsset is useless thing.
    I just want to get some info about scene like build index. But I have to make ultra difficult alghorithm to get it
    Why you just cant make things simple? I want to load scenes in runtime with SceneAsset, but I cant, I have to write own ScriptableObject decorator with buildIndex serialization.


    public class SceneContainer : ScriptableObject
    {
    [field: SerializeField, HideInInspector]
    public int sceneIndex { get; private set; }

    #if UNITY_EDITOR
    [SerializeField]
    private SceneAsset _sceneAsset;

    private void OnValidate()
    {
    string path = AssetDatabase.GetAssetOrScenePath(_sceneAsset);

    List<EditorBuildSettingsScene> editorBuildSettingsScenes = EditorBuildSettings.scenes.ToList();

    EditorBuildSettingsScene buildSettingsScene = editorBuildSettingsScenes.First(scene => scene.path == path);

    int buildIndex = editorBuildSettingsScenes.IndexOf(buildSettingsScene);

    if (sceneIndex == buildIndex) return;

    sceneIndex = buildIndex;
    }
    #endif
    }
     
  2. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    7,842
    It's an editor only thing because they don't exist at runtime. Scenes in your build settings get crunched up into a different file type for use in runtime.

    It's unwieldy, for sure. One of those old parts of Unity that we can't really shed without Unity doing some big breaking update that probably will never happen.

    The process for loading/unloading scenes is a lot more straightforward with Addressables as you can 'reference' scenes directly via an AddressableReference.
     
    Kurt-Dekker likes this.
  3. fr0zer

    fr0zer

    Joined:
    Apr 22, 2018
    Posts:
    3
    Thanks for reply. I will see how it works with addresables.
     
  4. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    5,882
    It's only perceived by you as ultra difficult. ;)
    For one, you are not using 'var' which makes your code far more verbose than it needs to be.
    Then you are not utilizing LINQ to its fullest. For instance, it works with arrays too.
    Lastly, you haven't cleaned up your code .. the second to last line doesn't make any sense. You can just assign it, regardless of whether the value might be the same or not.

    Here's my version:
    Code (CSharp):
    1. private void OnValidate()
    2. {
    3.     string path = AssetDatabase.GetAssetOrScenePath(_sceneAsset);
    4.  
    5.     var scenes = EditorBuildSettings.scenes;
    6.     var exists = scenes.FirstOrDefault(s => s.path == path) != null;
    7.     if (exists)
    8.         sceneIndex = scenes.TakeWhile(s => s.path != path).Count();
    9. }
    Pretty sure there may be a way to combine both the exists and count check but it's already simple enough to prove my point that there is nothing "ultra difficult" about this. And yes, I spent 2 minutes googling the LINQ usage myself and as usual, found the solutions on stackoverflow. I don't know these off the top of my head either.

    The first one just checks if the scene is in the list to begin with, because the TakeWhile only counts the ones that don't match to increment up to the desired index - which would be wrong (equal to last index) if we didn't check first whether the scene is actually in the build list.

    Exactly why I redesigned the AssetDatabase. :)
    I might be doing more of the same for other ~20 year old rotten API depending on where I consistently run into pains myself.
     
  5. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    5,882
    Side-note, this is BAAAAAD:
    Code (CSharp):
    1. #if UNITY_EDITOR
    2.         [SerializeField]
    3.         private SceneAsset _sceneAsset;
    4. #endif
    You can run into serious build issues if you #if out serialized fields because the serialization format then differs between editor and build.

    Depending on where you add more fields Unity will throw an error in builds noting that something is off about the serialization format of the scene and fail to load the scene.

    Have you tried to build and run this? If not, do that. If it works, add another [SerializeField] below the #endif and try again. At the latest that should throw an error in the build.

    You should move that code to an editor-only script.
     
  6. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    7,842
    This has been supported for a long time.
     
  7. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    5,882
    I stand corrected! :)

    Found the earliest mention in the 2021.2 manual:
    upload_2023-12-29_11-44-19.png

    I think last time I ran into this was with Unity 2018 or 2019 and ever since that was ingrained as a no-no given how awful it was to figure out the cause.
     
    spiney199 likes this.
  8. fr0zer

    fr0zer

    Joined:
    Apr 22, 2018
    Posts:
    3
    Its not difficult because I implemented this and gave you ready code. You just refactor it. But when you have only task: "make the runtime sceneAsset decorator because unity dont have it". You have to spent 20-30 minutes to find a solution.