Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Join us on March 30, 2023, between 5 am & 1 pm EST, in the Performance Profiling Dev Blitz Day 2023 - Q&A forum and Discord where you can connect with our teams behind the Memory and CPU Profilers.
    Dismiss Notice

Question How to wait for all additive scenes before executing logic?

Discussion in 'Scripting' started by Mauschelbaer, Jan 8, 2023.

  1. Mauschelbaer


    Aug 4, 2019
    In my game I have a Scene called "Loading". In it I load two scenes that make up the in-game screen: "Gameplay" and (e.g.) "TestMap01".

    Screenshot 2023-01-08 184406.png

    This is the code from my Loading-Scene which will load the in Game so it looks like in the screenshot:
    Code (CSharp):
    2. public class LoadingMenu : MonoBehaviour
    3. {
    4.     public void Start()
    5.     {
    6.         scenesToLoad.Add(SceneManager.LoadSceneAsync("Gameplay"));
    7.         scenesToLoad.Add(SceneManager.LoadSceneAsync("TestMap01", LoadSceneMode.Additive));
    8.         StartCoroutine(LoadingScreen());
    9.     }
    11.     IEnumerator LoadingScreen()
    12.     {
    13.         float totalProgress = 0;
    14.         for (int i = 0; i < scenesToLoad.Count; ++i)
    15.         {
    16.             while (!scenesToLoad[i].isDone)
    17.             {
    18.                 totalProgress += scenesToLoad[i].progress;
    19.                 loadingProgressBar.fillAmount = totalProgress / scenesToLoad.Count;
    20.                 yield return null;
    21.             }
    22.         }
    23.     }
    24. }
    However, I often have the problem that many Start() or Awake() methods from scripts are executed before the map (i.e. the second additive loaded Scene) has been loaded, so that a lot of the logic simply doesn't work (e.g.
    GameObject .Find(...)
    can't find anything yet because it doesn't exist yet).

    My question: How can or should I ensure that everything was finally loaded?
  2. Owen-Reynolds


    Feb 15, 2012
    Your LoadingScreen function looks fine -- it won't finish until all scenes have loaded. The problem is that Awake() and Start() don't interact with it. Of course the ones in the first scene run immediately, possibly before the other scene is loaded. Why wouldn't they?

    The fix I use is another start-like function in the "game manager" (the main script) for whatever got loaded -- call it start2 or runMeAfterAllIsLoaded or something. When LoadingScreen is completely done, have it find the main script in the new scene, and run the second Start (or have it set an "allLoadingDone" bool to tell someone else to do it).
  3. Mauschelbaer


    Aug 4, 2019
    That sounds great! Before I go into that, another problem:

    The strange thing is that I can't execute any logic outside of the while loop.
    Could it be because the "LoadingScene" is unloaded as soon as the first scene ("Gameplay"; NO additive) has finished loading and therefore the coroutine (which is in the script in the LoadingScene) is simply aborted/unloaded?

    Code (CSharp):
    2.     IEnumerator LoadingScreen()
    3.     {
    4.         float totalProgress = 0;
    5.         for (int i = 0; i < scenesToLoad.Count; ++i)
    6.         {
    7.             while (!scenesToLoad[i].isDone)
    8.             {
    9.                 totalProgress += scenesToLoad[i].progress;
    10.                 loadingProgressBar.fillAmount = totalProgress / scenesToLoad.Count;
    11.                 Debug.Log("...") //<------- OK
    12.                 yield return null;
    13.             }
    14.                 Debug.Log("...") //<------- not printed!
    15.         }
    16.                 Debug.Log("...") //<------- not printed!
    17.     }
  4. spiney199


    Feb 11, 2021
    Most likely. Coroutines are attached to the monobehaviours that started them. Once that scene is unloaded the coroutine will cease to run.

    You may need to do a step by step additive load, then have this initial scene unload itself (or have the loading scene unload it).