Search Unity

Showcase Pauses before start of Awake() of two Scenes loaded by LoadSceneAsync

Discussion in 'Scripting' started by DSivtsov, Jul 26, 2022.

  1. DSivtsov

    DSivtsov

    Joined:
    Feb 20, 2019
    Posts:
    151
    I made the Loader for game based on LoadSceneAsync():
    1. Initially is loaded the Loader Scene with LoaderManager (LoaderManager) script/GameObject.
    2. LoaderManager call LoadSceneAsync() for two scenes: Menus and Game.

    a) Scenes are loading with AsyncOperation.allowSceneActivation = false - the First scene ("Menu") will be activated (started) only after all scenes will be loaded and after certain statement - allowSceneActivation set to true (method named as "StartAfterLoadedAllScenes")

    b) Scenes are loading with (default AsyncOperation.allowSceneActivation = true) and every scenes will be activated (started) just after only after it will be loaded automatically (method named as "StartFirstLoadedScene")

    below TL;DR can skip and go to end to summary and to question/recommendation
    In Second case all works as predictable, bellow a log load:

    Legend:
    "LoaderManager (LoaderManager) [1] [Loader] StartFirstLoadedScene() : LoadCycle:"
    The scirpt LoaderManager (from GameObject LoaderManager) at Frame #1 from "Loader" Scene
    called the Debug.Log("StartFirstLoadedScene() : LoadCycle")

    "[0] currentOperation=0.9 totalIsDone=False"
    The current value AsyncOperation progress = .9 and isDone=false, [0] - Menu and [1] - Game scene
    1. LoaderManager (LoaderManager) [1] [Loader] StartFirstLoadedScene()
    2. LoaderManager (LoaderManager) [1] [Loader] StartFirstLoadedScene() : LoadCycle
    3. [0] currentOperation=0.9 totalIsDone=False
    4. [1] currentOperation=0 totalIsDone=False
    5. sum=0.9 45.00%
    6. LoaderManager (LoaderManager) [2] [Loader] StartFirstLoadedScene() : LoadCycle
    7. [0] currentOperation=0.9 totalIsDone=False
    8. [1] currentOperation=0.9 totalIsDone=False
    9. sum=1.8 90.00%
    10. MenuSceneManager (MenuSceneManager) [3] [Menus] Awake()
    11. LoaderManager (LoaderManager) [3] [Loader] StartFirstLoadedScene() : LoadCycle
    12. [0] currentOperation=1 totalIsDone=True
    13. [1] currentOperation=0.9 totalIsDone=False
    14. sum=1.9 95.00%
    15. LoaderManager (LoaderManager) [4] [Loader] StartFirstLoadedScene() : LoadCycle
    16. [0] currentOperation=1 totalIsDone=True
    17. [1] currentOperation=0.9 totalIsDone=False
    18. sum=1.9 95.00%
    19. GameSceneManager (GameSceneManager) [5] [Game] Awake()
    20. Temporary for [Game] Scene was activate [ButtonRestart] GameObject.
    21. LoaderManager (LoaderManager) [5] [Loader] StartFirstLoadedScene() : LoadCycle
    22. [0] currentOperation=1 totalIsDone=True
    23. [1] currentOperation=1 totalIsDone=True
    24. sum=2 100.00%
    25. LoaderManager (LoaderManager) [6] [Loader] AllScenesLoadedActivated()
    26. GameMainManager (GameMainManager) [6] [Loader] AllScenesLoaded()
    On step 10 was started the Awake() from Menu Scene
    On step 19 was started the Awake() from Game Scene
    On step 25 the LoaderManager detected that all scenes loaded and activated (started)
    Note. It made one "yield return null" before send "AllScenesLoadedActivated()" (Unity recommendation)

    But In Case One ("a)"), bellow a log load:
    1. LoaderManager (LoaderManager) [1] [Loader] StartAfterLoadedAllScenes()
    2. LoaderManager (LoaderManager) [1] [Loader] StartAfterLoadedAllScenes() : LoadCycle
    3. [0] currentOperation=0.003146853 currentOperation=False
    4. [1] currentOperation=0 currentOperation=False
    5. sum=0.001573427 0.09%
    6. LoaderManager (LoaderManager) [2] [Loader] StartAfterLoadedAllScenes() : LoadCycle
    7. [0] currentOperation=0.9 currentOperation=False
    8. [1] currentOperation=0.9 currentOperation=False
    9. sum=1.8 100.00%
    10. LoaderManager (LoaderManager) [3] [Loader] AllScenesLoadedActivated()
    11. MenuSceneManager (MenuSceneManager) [4] [Menus] Awake()
    12. GameSceneManager (GameSceneManager) [6] [Game] Awake()
    13. GameMainManager (GameMainManager) [7] [Loader] AllScenesLoaded()
    Exist a very strange and not clear behaviour:
    After step 9 - detection that all scene was loaded and after one "yield return null", the all loaded Scenes was activated (set
    allowSceneActivation= true)
    .
    On step 10 - LoaderManager scipt filling that all Scenes loaded and activated, but:
    Only On step 11 (Frame#4) will be called Awake() from Menus Scene. It's understandable (next Update after scene activation)
    But Only On step 12 (Frame#6) will called Awake() from Game Scene.
    It's a strange, I was awaited that it will in simultaneous with Menu Scene.
    For this case I made in LoaderManager() special delay before send the send "AllScenesLoadedActivated()" to GameMainManager.

    Summary
    In my case the special delay was the four "yield return null" between Awake()
    I don't know Is it the standard delay between finishing of activation Scenes which was fully loaded and after that activated simultaneously? or it depends on of content the Scenes and computer performance.
    Simple workaround - not use the simultaneous activation more than one Scene (it's a have some logic).
    I settled on that, that I will use the first variant "a)"
     
    Last edited: Jul 26, 2022
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,745
    Are you testing this in the editor? I seem to recall reading how the unity editor accurately replicates the async loading. Have you tried doing it in an actual build?
     
  3. DSivtsov

    DSivtsov

    Joined:
    Feb 20, 2019
    Posts:
    151
    Initially I tested it in Editor, but that the result from build:
    (I little change the format of output - the Frame number now in the beginning of line - "[102]" (at Frame#102)
    1. [102] LoaderManager (LoaderManager) [Loader] AllScenesLoadedActivated()
    2. [103] MainMenusSceneManager (MainMenusSceneManager) [Menus] Awake()
    3. [105] GameSceneManager (GameSceneManager) [Game] Awake()
    4. [106] GameMainManager (GameMainManager) [Loader] AllScenesLoaded()
    The result is the same:
    On step 2 (Frame#103) was called the Awake() from [Menus] Scene
    And only on step 3 (Frame#105) was called the Awake() from [Game] Scene
    !!! And again the "delay (which) was the four "yield return null" between Awake()" are "syncing" the loader state ([Loader] AllScenesLoadedActivated() on Frame#102, Step 1) with real state the AllScenesLoaded() on Frame#106 (Step 4).

    I don't know why that works as it is,
    But if Imagine that all "Activate Scene after Loading" commands use the one Thread, it can explain that behavior.
    Do you know, if you loaded async two Scenes (with option "allowSceneActivation= false") you can't activate the Second Scene before First ("First" - the scene which was started loading first)
     
  4. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    7,930
    If I remember correctly from various bits of Unity documentation (particularly in the addressables documentation), scenes, loaded either sync or async, need to be 'integrated' into the main thread and this always happens asynchronously I believe.

    So we can probably also assume that Unity can only integrate one scene at a time, and this may potentially take more than one frame. Also a potential is that Unity 'pads out' multiple scenes needing to be integrated by putting a frame in between them.

    Hard to say for certain though, as the whole SceneManager/scene loading stuff is very much black box. I'm just making educated guesses here.

    Personally I wouldn't rely on scenes loading 'all at the same time'. Ideally they should be able to load in any order and not rely on any other scenes already being present.
     
    Kurt-Dekker likes this.
  5. DSivtsov

    DSivtsov

    Joined:
    Feb 20, 2019
    Posts:
    151
    I meant to use the load scenes option as "all at the same time", but remember that they won't load at the same time. :)
    if demanded the hard control for the loading scene IMHO the best solution use "the loading all scenes at the same time" and additionally use call back set onto Awake() methods of this scenes... or not load than one Scene for one time