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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice
  4. Dismiss Notice

SceneManager.LoadSceneAsync and getting REAL loading times

Discussion in 'Scripting' started by programmrzinc, May 7, 2016.

  1. programmrzinc

    programmrzinc

    Joined:
    May 29, 2011
    Posts:
    79
    Hey community,

    I'm loading a pretty big environment through SceneManager.LoadSceneAsync, but when I first initiate the load, the async progress jumps from 0.0 to 0.9 in like one frame, and then I wait for ~90-100 seconds for the scene to actually load/switch, or whatever is happening on the preloading thread. I don't mind the wait time, But I do need to know the exact percentage of completion. Is there a way to do this?

    Here's my current code :
    Code (CSharp):
    1.  
    2. public IEnumerator LoadMyLevel()
    3.     {
    4.         PhotonNetwork.isMessageQueueRunning = false;
    5.         AsyncOperation async = SceneManager.LoadSceneAsync(LevelInfo.LevelName, LoadSceneMode.Single);
    6.         async.allowSceneActivation = false;
    7.         while (async.progress < 0.9f)
    8.         {
    9.             StatusText.text = "<Loading Map : " + LevelInfo.LevelName + " : " + (100f * async.progress).ToString("F0") + ">";
    10.         }
    11.         StatusText.text = "<Loading Complete : " + LevelInfo.LevelName + " : " + (100f * async.progress).ToString("F0") + ">";
    12.         async.allowSceneActivation = true;
    13.         while(!async.isDone)
    14.             yield return async;
    15.        
    16.            
    17.     }
    18.  
     
  2. kru

    kru

    Joined:
    Jan 19, 2013
    Posts:
    452
    It could be that the scene doesn't take long to load at all, especially if most of the art and sound assets are already in memory from a previous scene, but the first frame of your new scene, or the last frame of the current scene, could be what is taking the time. If you have expensive operations taking place in Awake, OnEnable, or Start of the new scene, they could be dragging out that frame time. If you have expensive operations taking place in OnDisable or OnDestroy of your current scene, those could drag out the frame time.
     
  3. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,380
    There's loading the assets and what not, and then there's initializing the assets. The 0.9 to 1 is the initializing. And it's taking a while.

    There's no actual way to know how long a load will actually take. There's no actual way for unity to even know how long your scene takes to initialize...

    So here in lies a big problem... when we know we have 1000megs of data to load into memory... we can tell how far a long we are. We've loaded 500megs, so we have 50% left.

    BUT, when we have tons of initialization stuff, there's no metric to measure by. We don't know how many of what are whats. The loader could come up with some analytics to count how many things are to be initialized and as it goes through the list it tallies stuff off and whatnot... but this is actually a lot of work that would add even more load time, as well as complicate the loading code (we have to use the tracking load code when loading through SceneManager, where as we use the faster when calling Instantiate). So it's more work and code for the Unity devs, to result in slower load times... for what, so that those people who want to show a loading bar have a bay that doesn't stall out for a little it of its progression?

    You ever notice how most of those bars for other things (like installers) do the SAME thing, they seem to do large sections of loading super d, duper fast, but others super d-duper slow.

    This is why... some things just aren't so easy to track.

    Now if you don't like it jumping to 90% then sitting at 90% for a while then jumping to 100%... how about you do this.

    For the first 90%, scale the number to be from 0->50%.

    Then while initializing add to the 0.5 little tiny bits every frame until it's done.

    Now the bar appears to be progressing more accurately then before, though still not actually accurate... because it couldn't be accurate. And why does it matter? (heck, why do you think so many games just have a spinning logo or what not when loading...)

    Like this:

    Code (csharp):
    1.  
    2. while(async.progress < 0.9f)
    3. {
    4.     var scaledPerc = 0.5f * async.progress / 0.9f;
    5.     StatusText.text = "<Loading Map : " + LevelInfo.LevelName + " : " + (100f * scaledPerc).ToString("F0") + ">";
    6. }
    7.  
    8. async.allowSceneActivation = true;
    9. float perc = 0.5f;
    10. while(!async.isDone)
    11. {
    12.     yield return null;
    13.     perc = Mathf.Lerp(perc, 1f, 0.05f);
    14.     StatusText.text = "<Loading Map : " + LevelInfo.LevelName + " : " + (100f * perc).ToString("F0") + ">";
    15. }
    16.  
    17. StatusText.text = "<Loading Complete : " + LevelInfo.LevelName + " : 100>";
    18.  
     
    pixelR and Velo222 like this.
  4. programmrzinc

    programmrzinc

    Joined:
    May 29, 2011
    Posts:
    79
    hmmm, I see what you mean. I'll see if I can trim the initialization stuff in the scene that supposed to be loaded, as well as cheat the progress bar. Thanks guys for the "solution" lol
     
  5. programmrzinc

    programmrzinc

    Joined:
    May 29, 2011
    Posts:
    79
    whoa! I substituted your code in my script and the great big scene took about 3 seconds to load! What type of magic are you using? @lordofduct