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. Dismiss Notice

Question Program Hanging during Async dowhile loop

Discussion in 'Scripting' started by puddleglum, Jul 18, 2023.

  1. puddleglum

    puddleglum

    Joined:
    May 11, 2020
    Posts:
    380
    im having issues with a scenemanager async loop

    Code (csharp):
    1.  
    2.     public async void LoadScene(int SceneIndex)
    3.     {
    4.    
    5.         _LoaderCanvas.SetActive(true);
    6.         var Scene = SceneManager.LoadSceneAsync(SceneIndex);
    7.         Scene.allowSceneActivation = false;
    8.  
    9.  
    10.         do
    11.         {
    12.             Debug.Log(Scene.progress);
    13.             await Task.Delay(100);
    14.         } while (Scene.progress <= 0.9);
    15.  
    16.         Scene.allowSceneActivation = true;
    17.  
    18.         _LoaderCanvas.SetActive(false);
    19.  
    20.  
    21.  
    22.     }
    23.  
    PS: when i say hang i mean, the scene is loaded, the code is running, things are happening like animations, but it will never continue to the next step

    this hangs indefinitely, and never loads the next scene, until i click off of the unity play window, and click back on it. when i do that, it immediately loads the next scene. 0 clue why this happens.
    the debug.log() returns 0 in the first frame, and then .9 in all subsequent frames.
    also the await Task.delay is necessary. removing it causes the scene to actually hang forever, and crash unity
     
  2. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    5,856
    I honestly wouldn't use async code with the old scene-loading AsyncOperation. It's designed to work with co-routines.

    If you're looking to use async code for scene loading, you'd be better off using addressables.
     
  3. puddleglum

    puddleglum

    Joined:
    May 11, 2020
    Posts:
    380
    alr ill switch over to coroutine, i was just using async cause i was following tarodevs scene manager tutorial lol

    however i would still like to run functions while this scene is loading, and idk if Ienumerator runs simultaneously.
     
    Last edited: Jul 18, 2023
  4. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    5,856
    It can probably be made to work with UniTask: https://github.com/Cysharp/UniTask

    Which is an async package that provides a bunch of extra Unity support for async code.
     
    puddleglum likes this.
  5. OutDoorsScene

    OutDoorsScene

    Joined:
    Sep 9, 2022
    Posts:
    140
    @puddleglum Does your pc crash if you use this format for loading a scene?
    Code (CSharp):
    1.   AsyncOperation LoadOP = SceneManager.LoadSceneAsync(NewSceneToLoad);
    2.         while (LoadOP.isDone != true)
    3.         {
    4.             await Task.Yield();
    5.         }
     
    spiney199 likes this.
  6. BABIA_GameStudio

    BABIA_GameStudio

    Joined:
    Mar 31, 2020
    Posts:
    488
    According to the manual for AsyncOperation (which the LoadSceneAsync returns):
    "If you set allowSceneActivation to false, progress is halted at 0.9 until it is set to true."

    Your while loop is based on
    Scene.progress <= 0.9
    , so it will never exit the loop as the progress stays at 0.9 until allowSceneActivation is set to true (which you only do after exiting from your while loop).

    Your loop should be
    while (Scene.progress < 0.9);
     
    MaskedMouse, Bunny83 and spiney199 like this.
  7. puddleglum

    puddleglum

    Joined:
    May 11, 2020
    Posts:
    380
    oooh ok icic
     
  8. puddleglum

    puddleglum

    Joined:
    May 11, 2020
    Posts:
    380
    for some reason Scene.isDone always returns false untill the scene is active
     
  9. BABIA_GameStudio

    BABIA_GameStudio

    Joined:
    Mar 31, 2020
    Posts:
    488
    If you're checking it with your existing code, then that makes sense. Again, this is explained in the manual:
    "When allowSceneActivation is set to false, Unity stops progress at 0.9, and maintains isDone at false."

    So if you wanted to use isDone then you would have your while loop checking that isDone is false, and then within that loop you would use an if check for progress being >= 0.9f and if it is then set allowSceneActivation to be true.

    There is even an example that does exactly this in the manual (under allowSceneActivation):
    https://docs.unity3d.com/ScriptReference/AsyncOperation-allowSceneActivation.html
     
  10. Hikiko66

    Hikiko66

    Joined:
    May 5, 2013
    Posts:
    1,302
    The Async function is running on the main thread. If you don't await it, it's just a normal function that runs until it completes, so it would hang the program until your scene is loaded even if your loop logic worked. Yield is a better await condition in this case, because you want to check the progress every frame because you want things to happen as quickly as possible.
     
  11. puddleglum

    puddleglum

    Joined:
    May 11, 2020
    Posts:
    380
    that makes sense
     
  12. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,713
    Exactly... Or as I like to put it...

    "Yield early, yield often, yield like your game depends on it... it does!" - Kurt Dekker

    (or await in this case)

    Unity will lock up 100% of the time EVERY millisecond your scripting code is running.

    Nothing will render, no input will be processed, no Debug.Log() will come out, no GameObjects or transforms will appear to update.

    Absolutely NOTHING will happen... until your code either:

    - returns from whatever function it is running

    - yields from whatever coroutine it is running

    As long as your code is looping, Unity isn't going to do even a single frame of change. Nothing.

    No exceptions.
     
    puddleglum likes this.