Search Unity

Avoiding a twice-loading scene in SceneManager.LoadSceneAsync

Discussion in 'Scripting' started by doublegumbo, Sep 22, 2019.

  1. doublegumbo

    doublegumbo

    Joined:
    Oct 24, 2013
    Posts:
    53
    Using Unity 2018.3.14f1

    I am making a multi-scene game where a player enters a trigger and a scene loads asynchronously.

    This scene has some substantial light-mapping data, so the scene takes about seven seconds to load asynchronously*.

    One of my testers was able to accidentally make the level load twice by leaving the trigger while the scene was loading and then re-entering it.

    As you'll see below, I have a script that checks that when the player leaves the trigger, the scene will unload if it is already loaded. Another function does the opposite.

    Problem is, if the scene is still in the middle of an asynchronous load and the player leaves the trigger, the scene won't know to unload because the scene isn't actually fully loaded - it's in some sort of ambiguous state between loaded and unloaded. Then when the player enters the trigger again, the SceneManager still thinks its unloaded, so the scene starts its async load a second time.

    *This seems to happen during the first time the game is played. After that, all the relevant data is in memory and async loading happens much faster. That's part of why this has been hard to test / catch.

    What's the way forward here? I'm thinking an AsyncOperation technique in my coding work is the way forward, but I could use some perspective.

    thanks!
    -CMD

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.SceneManagement;
    5.  
    6. public class SceneLoadMaster : MonoBehaviour {
    7.  
    8.  
    9.     //broadcast that the level is, in fact, loaded
    10.  
    11.    // scriptable object for all my scenes
    12.     public SceneDatabaseSO sceneDatabase;
    13.  
    14.    // events attached to other scripts that let this script know to load a new secne.
    15.     void OnEnable()
    16.     {
    17.         SceneLoadProxy.SceneLoadEvent += SceneLoad;
    18.  
    19.         SceneLoadProxy.SceneUnLoadEventBypass += SceneUnload;
    20.         SceneLoadBlockerFadeControl.SceneUnLoadAfterBlocker += SceneUnload;
    21.  
    22.         // SceneManager.sceneUnloaded += SetSceneStateToUnloaded;
    23.     }
    24.  
    25.     void OnDisable()
    26.     {
    27.         SceneLoadProxy.SceneLoadEvent -= SceneLoad;
    28.  
    29.         SceneLoadProxy.SceneUnLoadEventBypass -= SceneUnload;
    30.         SceneLoadBlockerFadeControl.SceneUnLoadAfterBlocker -= SceneUnload;
    31.  
    32.         // SceneManager.sceneUnloaded -= SetSceneStateToUnloaded;
    33.     }
    34.  
    35.    // the scene loads by receiving a level string from a Scriptable Object attached to a scene trigger.
    36.   // if that string matches a scene name on the SceneManager, we load it.
    37.     public void SceneLoad(SOLevelString l){
    38.      
    39.         if (l)
    40.         {
    41.             Scene scene = SceneManager.GetSceneByName(l?.value);
    42.             if (!scene.isLoaded)
    43.             {
    44.                 print("loading... "+l+" because it's not loaded yet.");
    45.                 SceneManager.LoadSceneAsync(l.value, LoadSceneMode.Additive);
    46.             }
    47.         }
    48.         else
    49.         {
    50.             print ("there's no level to load.  what are you doing?!");
    51.         }
    52.     }
    53.  
    54.    // the opposite happens here.
    55.     public void SceneUnload(SOLevelString l){
    56.  
    57.         Scene scene = SceneManager.GetSceneByName(l?.value);
    58.      
    59.         if (l)
    60.         {
    61.             if (scene.isLoaded)    //
    62.                 {
    63.                     SceneManager.UnloadSceneAsync(l.value);
    64.                     return;
    65.                 }
    66.             else
    67.                 {
    68.                     print("The level is already unloaded!");
    69.                 }
    70.         }
    71.         else
    72.         {
    73.             print ("there's no level to unload.  what are you doing?!");
    74.         }
    75.     }
    76.  
    77. }
    78.  
     
  2. Dextozz

    Dextozz

    Joined:
    Apr 8, 2018
    Posts:
    493
    jaimehvazz likes this.