Search Unity

Please help with async loading screen

Discussion in 'Scripting' started by MisterMatt, Sep 30, 2014.

  1. MisterMatt

    MisterMatt

    Joined:
    Oct 24, 2012
    Posts:
    13
    I have been at this for several days and have had no luck. I am trying to get a loading scene to work while generating a level in the background. The Scene I am loading has a SceneManager script that creates terrain and loads various prefabs from resource.load, etc. This all happens in either the Awake or Start method (I have been trying both).

    I have been trying the LoadLevelAsync and LoadLevelAdditiveAsync and can not find a straight answer anywhere on whether or not these async methods will run everything in my Awake/Start.


    Without using the LoadLevelAsync I was able to get a static version working.

    Here is some of the code for that in another unanswered question:
    http://answers.unity3d.com/questions/799462/loading-screen-for-random-generated-level.html

    This is an Oculus rift demo I want to release, but the level generation takes so long I wouldn't want to put a user in the rift with no visual feedback that the scene is still loading

    I tried asking the same thing in the Oculus forums with no luck:
    https://developer.oculusvr.com/forums/viewtopic.php?f=37&t=15137

    I recently retried every variation I could possibly think of as the following thread gave me some new hope that I might just need to build first (rather than use the editor) to get the desired results, but again no luck:

    http://forum.unity3d.com/threads/simple-animation-during-loading-not-possible-in-unity.133761/

    Is there any hope to get this working and get a background thread to load a scene with dynamic logic while playing an animation? (ideally the user would be able to look around in the rift but I am alright with static as long as I can play an animation showing them it is working)

    Thank you in advance for any kind soul willing to help! :)
     
  2. ZO5KmUG6R

    ZO5KmUG6R

    Joined:
    Jul 15, 2010
    Posts:
    490
    I really do hope someone has the solution to this. It would help me also as I am stuck with a static loading screen as well.
     
  3. Vipsu

    Vipsu

    Joined:
    Oct 8, 2012
    Posts:
    88
    You can do this by creating a static class that handles the scene transition. Then you need a nearly empty scene that loads up the target scene specified in the static class.

    Then you need make a persistent UI object which renders above everything on the scene, effectively hiding everything that happens on the background. You need instantiate this just before changing the scene and since it's persistent it will stay on top of everything from Scene1 -> LoadingScreenScene -> Scene2. Then on the target scene (Scene2) you will initialize your level on the background and destroy the UI Object when you are done.

    If you want to animate the loadingscreen while initializing your level/scene you probably need to cut your intialization in to chunks and handle them one by one in update or co-routine so the animations get process time.
     
  4. MisterMatt

    MisterMatt

    Joined:
    Oct 24, 2012
    Posts:
    13
    Vipsu, thank you for this response.

    I have my scripts as a MonoBehaviour, how could I make this static and still have it start up with the scene or transition the scene? Is there some trick that can be gained from using a static class to load things?

    Currently for AddLevelAsync or AddLevelAdditiveAsync I have this order of operations:

    Scene1 LoadingManager(MonoBehaviour)
    Start -
    Get handle of existing UI element
    Load Async Scene In Coroutine

    Update -
    Update rotation once per second
    Check for load completion of asyncOperation
    If Complete, Load​


    Scene2 SceneManager(MonoBehaviour)
    Start or Awake - (tried both) (Also below methods I have tried with/without coroutines at the top level)
    Load random terrain
    Add trees, plants, etc. to terrain
    Create pathfinding GridGraph
    etc...
    (if LoadLevelAsyncAdditive) DisableUIComponents from Scene1​

    Update -
    Enjoy the new world that was created for you :)

    In regards to chunking up work, I will modify some of it to batch into coroutines tonight, but creating the pathfinding GridGraph relies on an external third party library.

    Ideally I would like to spin off a new task and use continuation (I am really hoping some of this comes with unity 5's multithreading). I feel like I should be able to batch these into a separate thread and let my UI thread run free until it is finished loading.

    Or even a simpler solution this should be completely possible with at least LoadLevelAsync and treated as a separate thread even if the Rendering engine is not threadsafe LoadLevelAsync should handle that separately in the background until Start/Awake complete and pause the scene until the user triggers a transition.
     
  5. ThermalFusion

    ThermalFusion

    Joined:
    May 1, 2011
    Posts:
    906
    What happens in start and awake is handled after a scene has loaded, not as part of the unity loading thread.
    If you have heavy code generating things there you will need to spread it out over several frames in order to give the UI a chance to update.
     
  6. MisterMatt

    MisterMatt

    Joined:
    Oct 24, 2012
    Posts:
    13
    This is extremely frustrating and it should be easy to do this simple thing. I am hoping that the new multi-threading functionality in Unity 5 will help solve this type of issue.

    More things I have tried with no success
    • Using Constructor of SceneManager : MonoBehaviour to try and force this to fall into the Scene loading (Would not load constructor, could be something here even though there are a lot of threads saying not to use constructor for MonoBehaviours... this could be a valid reason if someone gets it to work)
    • Tried using the "OnLevelWasLoaded" method instead with no luck (figured I would try it after reading this: http://answers.unity3d.com/questions/59873/onlevelwasloaded-called-before-awake.html)

    I have created a class that will lock a queue and throw delegates back onto it to process in the main thread (when needed) and have solved the problems to batch those up and get a reasonable framerate out of my own code, but when loading from a third party library (scan grid graph) that is out of my control and the third party library is using unity objects so it creates errors when I try throwing it into another thread.