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

Bug Loading scene takes a long time to load, then LoadSceneAsync finishing instantly

Discussion in 'Scripting' started by AFriendlyUnityDeveloper, Dec 14, 2022.

  1. AFriendlyUnityDeveloper

    AFriendlyUnityDeveloper

    Joined:
    Dec 26, 2018
    Posts:
    32
    My Problem:

    LoadSceneAsync always goes from 0 to .9 instantly for me.

    My situation:

    I have a unity app with a tiny initial loading scene that runs when opening the game and then a much larger game scene afterwards.

    When the user first opens the app it goes to scene 0 (my small loading scene).

    What I expect:
    - Unity splash screen for 2 seconds
    - Loading scene opens very quickly.
    - Loading scene shows 0-100 progress bar over a few seconds
    - Eventually the scene transitions to Scene 1, the bigger scene

    What happens:
    - I get the Unity splash screen for 2 seconds
    - Very long pause staring at black screen
    - Loading scene opens and instantly jumps to done
    - Scene transition to the big scene

    What's going on here? Is Unity for some reason pulling all my assets into memory during its own splash screen when it opens? (or during the loading of my first scene?)

    Does it matter that I am on the free version of unity? Do I need to upgrade to make this actually work?
     
    Last edited: Dec 14, 2022
  2. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    5,849
    You'd have to use the profiler/memory profiler to find out. The player.log file also gives some timings when launching an application.

    No, definitely not.

    Keep in mind there are some things that can greatly extend a built Unity's game boot up time. For example, a large number of files in Resources files has an impact on start up time.
     
  3. AFriendlyUnityDeveloper

    AFriendlyUnityDeveloper

    Joined:
    Dec 26, 2018
    Posts:
    32
    Thanks for the response!

    I just checked this, I see nothing useful in Player.log. Its only got a few lines before it makes it past my 'tiny loading scene', none of which seem to indicate where it is spending this time loading things. (ie all of the timings sum up to well under 1 second)
     
    Last edited: Dec 15, 2022
  4. AFriendlyUnityDeveloper

    AFriendlyUnityDeveloper

    Joined:
    Dec 26, 2018
    Posts:
    32
    Is there a way I can get the logs file to be more verbose to show something that might point me in the right direction?

    I have to admit, I am at a bit of a loss here. I am not sure how to approach debugging his issue.
     
  5. AFriendlyUnityDeveloper

    AFriendlyUnityDeveloper

    Joined:
    Dec 26, 2018
    Posts:
    32
    Oh, I think I see the files you are referring to.

    I have basically 3 files which are large:
    1) resources.assets.resS - around 1 gig, (not sure when this is loaded. I would assume not for my tiny loading scene as that tiny scene has basically no dependencies)
    2) level2 - around 100 MB (I assume that this only loads when I load Scene 2)
    3) sharedassets2.resS - around 1 gig (I also assume this is only loaded when I load scene 2)

    All the documentation I can find on the second 2 seems to reinforce my belief. That leaves me with #1. How is this built? Is unity putting a bunch of shared stuff in there and blowing up my tiny loading scene by loading it for everything somehow?

    Edit: It turns out this is a weird Unity feature where it moves stuff into resources.assets.resS if you have things in any folder named "Resources". I renamed my folders and now that files size is tiny also.

    And I still have the same problem. The game goes from unity to splash screen to my tiny loading screen only after about 8 seconds. :(
     
    Last edited: Dec 15, 2022
  6. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    5,849
    That's a large resources folder. Note that your packages may have assets included in Resources folders. Anything you get from the asset store might be doing the same. I know that packages like TMPro have (small amounts) of assets included in Resources folders.

    It's not loaded into memory on application start, but the look up table for loading the assets is de-serialised, and depending on number of assets, can impact on loading time.
     
  7. AFriendlyUnityDeveloper

    AFriendlyUnityDeveloper

    Joined:
    Dec 26, 2018
    Posts:
    32
    Yup, you are right, its a super weird feature, not sure why they would do that instead of just having things load via dependency trees from scenes.

    I renamed all my resources folders to "Rsc". That removed the file you are pointing out.

    However, that still doesn't fix my problem and doesn't appear to be the root cause. Now my Resources folder is tiny but the game still hangs for a very long time on transitioning from the splash screen to the 'small loading screen'.
     
    Last edited: Dec 15, 2022
  8. tleylan

    tleylan

    Joined:
    Jun 17, 2020
    Posts:
    524
    I'll start by saying I don't know the answer BUT I can reasonably speculate that much of the loading is library code (the engine) that is needed to render anything. And... we have no idea what your loading scene is doing is it possibly the source of the issue?

    It isn't fun but perhaps create a simple substitute for your "big scene" as a test (but don't make it big). See if that behaves the same. If so put your big scene back into the build and modify your loading scene (again making it do virtually nothing) and see what effect it has.

    As for the free license I wouldn't think so. The license clearly spells out the conditions for usage and "Let's slow the loading of customer's apps" would negatively affect sales.
     
  9. AFriendlyUnityDeveloper

    AFriendlyUnityDeveloper

    Joined:
    Dec 26, 2018
    Posts:
    32
    Thanks for responding!

    My normal build: 2 very small scenes, 2 big ones (~1 gig .resS files)

    This has a long pause when going from splash screen to my very small loading screen

    Test build: Only 2 very small scenes

    This has a very short pause when going from unity splash screen to my very small loading screen (which then transitions to the other small scene)

    Every sign points towards later scenes affecting initial load times. But everything I know about Unity and scene loading says this should never happen.

    I don't really know what to do. What could cause resource files from later scenes to affect early scenes so negatively? That shouldn't happen, right?

    The loading screen is simple, its basically an image, text that shows the percent complete, and a call to LoadSceneAsync.

    Obviously something is wrong with my environment/build, but I dont know what. Im not really sure where to look or how to debug this.
     
  10. tleylan

    tleylan

    Joined:
    Jun 17, 2020
    Posts:
    524
    Again I'm not the person with the authoritative answers but I personally wouldn't guess too much about how Unity loads projects. It would take research (that I'm not willing to do) for you to find out. I'm certain the information is available you simply have to dig around where very few people do. It isn't unlike wanting to know how something in .Net works so you're stuck reviewing the source of stepping though with a debugger.

    And again I don't know what sizes you're talking about or what those scene's contain or whether they initialize by loading data from a remote server (or anything else).

    I would guess that the initial load of the Unity core libraries is very much affected by what you are doing. .Net wouldn't load in encryption services (just for one example) if you didn't call it somewhere but they may load in at startup rather than just before the service is called. You can see that sort of thing happening in web apps. It doesn't know if a user is going to push a button but the code behind the button (depending upon how it is written) will be loaded when the page loads.

    If I had the issue and wanted more information I would a) experiment a bit more and b) find a group that specializes on inspecting internal details not normally visited by app developers. To answer your specific question someone would need to see all the code to check for anything obviously amiss. People can guess but that's pretty much it.
     
  11. MaskedMouse

    MaskedMouse

    Joined:
    Jul 8, 2014
    Posts:
    1,058
    Use the profiler. You can check what is taking precious CPU time during start up as well as memory snapshots of what is getting loaded in.

    Unity doesn't take long to boot up your game unless you make it load a lot of things.
    If you want a fast boot, use a lightweight scene as bootstrap. Don't reference any game related assets in that scene.
    Load up the loading screen scene. Then load up the main menu scene async. Pass the progress to the loading screen. If they're separate scenes you can pass the progress through a singleton instance of the loading screen or a scriptable object asset being shared between the two.

    If you're relying on
    Resources.Load
    , don't. Unless you really have to.
    For example with TMPro, you don't have a choice. The underlying code will load it in with Resources.Load.
    But if you can avoid it, use Addressables instead. Even Unity themselves don't recommend using the Resources folder. Like they stated this in a tutorial on the Unity Learn.

    For the rest, none knows what you're doing. All ppl can give here are some tips and tricks.
    We don't know your project, we don't know your system you're testing on. Not even what Unity version you're using.
     
    Last edited: Dec 15, 2022
  12. tleylan

    tleylan

    Joined:
    Jun 17, 2020
    Posts:
    524
    Don't mean to hijack the thread but perhaps you know. I jumped on the Addressables bandwagon and was very happy with the results but I couldn't for the life of me figure out how to package them up for delivery to the headset. It all worked when running in the editor but didn't when I installed it.

    Are you aware of any "here is how you do it in 5 easy steps" video or tutorial of some kind?
     
  13. MaskedMouse

    MaskedMouse

    Joined:
    Jul 8, 2014
    Posts:
    1,058
    Just the default settings are already set to local build & load path. Which means they'll be built-in with your application.
    If you're on the latest addressables, it should already build the addressables for you on player build.
    Not sure what happens if you have a custom player build script. But just in case you can build the addressables before you build the player.

    upload_2022-12-15_16-24-29.png

    If you have addressable assets distributed online for updating purposes, group those assets and set them to the online path. Have a local and server profile so you can test locally "online" and actually from a server online.
    Then you can just switch between profiles instead of having to change the online path everytime you want to test something.

    CodeMonkey explains quite a lot about addressables.
     
  14. AFriendlyUnityDeveloper

    AFriendlyUnityDeveloper

    Joined:
    Dec 26, 2018
    Posts:
    32
    Appreciate the responses and attempts to help. I did learn a bit from your responses, particularly about the trap that is 'Resources' folder. (a lot of those unity asset store packs are dumping tons of stuff in here! I was able to shave hundreds of MBs off of my build size!) I also didn't realize I could analyze this in the profiler.

    I did end up "solving" this after a sleepless night. (although it seems weird that my solution actually solved it, it feels more like I found a hack/workaround to whatever the real problem is)

    I spent a lot of time googling this and couldn't find anything useful so I will leave my workaround here for anyone who lands here via google search and finds it useful:

    My splash screen code before the hack:
    Code (CSharp):
    1.    void Start()
    2.     {
    3.         StartCoroutine(LoadLobbySceneAsync());
    4.         DontDestroyOnLoad(this.gameObject);
    5.     }
    6.  
    7.    IEnumerator LoadLobbySceneAsync()
    8.     {
    9.         AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(SceneIndexes.GetLobbySceneIndex());
    10.         while(!asyncLoad.isDone)
    11.         {
    12.             PercentageDoneText.text = ((int)(100f*asyncLoad.progress/.9f)).ToString() + "%";
    13.             yield return null;
    14.         }
    15. }
    It turns out that calling load async from start was causing the scene to stop everything and not render until lobby scene fully loaded. (AFAIK this shouldn't happen, but it did)

    My fix: I just moved "StartCoroutine(LoadLobbySceneAsync());" call to fixed update and invoked it only after a few frames had gone by.

    Honestly, it feels like I found a hack, not the real solution. (If anyone has a guess/tips as to what the real solution is I would love to hear them!) I can't help but think I have something wrong with my environment elsewhere that would cause it to behave this way. But it does work.
     
    Last edited: Dec 15, 2022
    chriscode likes this.
  15. MaskedMouse

    MaskedMouse

    Joined:
    Jul 8, 2014
    Posts:
    1,058
    That sounds like a nasty and unnecessary fix.
    The code before your change looks fine. You got a
    yield return null
    in your while loop too so it gives control back to Unity everytime. There are many beginners that create a while loop without and question as to why Unity is locking up permanently.

    Indeed it shouldn't. Use the profiler.
    If your lobby scene has a lot of Awake scripts that do all kinds of expensive things that could cause a spike as well.
    Then again the loading screen should hide these kinds of loading hitches. That's what a loading screen is for.

    unrelated minor optimization
    Just a minor optimization would be to use TMPro's SetText method. It doesn't allocate garbage in a build.
    It does in the editor slightly but not in a build.
    PercentageDoneText.SetText("{0:0}%", asyncLoad.progress * 100f);


    With your line
    ((int)(100f*asyncLoad.progress/.9f)).ToString() + "%";
    you're generating a string from the integer and then concatenating it with another string (the %) resulting into another new string.
    But like I said, that's a minor optimization. It isn't a cause for concern if you left it that way. Just the garbage collector doing some work eventually that can cause a lag spike.
    If you have other text elements in your game that changes a lot per frame. for example a timer. Use SetText without +'s in your string.
     
  16. AFriendlyUnityDeveloper

    AFriendlyUnityDeveloper

    Joined:
    Dec 26, 2018
    Posts:
    32
    I did, when I call it from start it has the entire lobby+assets loading in a single frame, giant spike.

    When I move it to fixed update and call a tenth of second later works as expected.

    Its a big scene with a bunch of scripts, but I my understanding matches yours, it shouldn't be loading every asset in that scene in one frame just because of those awake scripts.

    Cool, thanks for the tip. The silver lining to this headache is that I learned a lot of unrelated stuff from this thread. :)
     
  17. MaskedMouse

    MaskedMouse

    Joined:
    Jul 8, 2014
    Posts:
    1,058
    Would you mind sharing a screenshot of the profiler at that spike?

    Also what you could try is yielding one frame and then loading in the lobby scene.
    Or wait for a second before loading the lobby scene.
    Code (CSharp):
    1. void Awake() => DontDestroyOnLoad(gameObject);
    2.  
    3. IEnumerator Start()
    4. {
    5.     yield return null;
    6.     // yield return new WaitForSeconds(1f);
    7.     StartCoroutine(LoadLobbySceneAsync());
    8. }
     
    Last edited: Dec 15, 2022
  18. chriscode

    chriscode

    Joined:
    Mar 2, 2015
    Posts:
    44
    I had to do similar just today: slightly delay next scene load, else froze before anything appears on screen. Feels like a hack indeed.