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. Voting for the Unity Awards are OPEN! We’re looking to celebrate creators across games, industry, film, and many more categories. Cast your vote now for all categories
    Dismiss Notice
  3. Dismiss Notice

Async loading not really working

Discussion in 'Editor & General Support' started by Robdon, Jun 8, 2018.

  1. Robdon

    Robdon

    Joined:
    Jan 10, 2014
    Posts:
    141
    I've spent quite a bit of time now trying to get my scene to load without any frame rate drops, so that I can play animations/particles during the load of my level(s).

    I've spent lots of time optimizing my code, specifically Awake() and OnEnable() to make sure that when I use LoadSceneAsync() there isn't lots to do during the 'Activation' phase, and managed to get it working quite well. I'm using it in LoadSceneMode.Additive mode.

    I'm now down to 2 last problems.

    1) TextMeshPro. It seems there is quite a bit of code running in Awake() / OnEnable() which causes a 0.05s delay if the loaded scene has any TextMeshPro object on it. Which I have no control over what Awake does.
    I seem to be able to get around this by having a single TextMeshPro object in the calling scene, and hide it after one frame before loading. So there must be some caching or something going on. Although that's a bit of a 'hack', at least gives me an option to remove this spike.

    2) Textures.If any GOs have textures on them (Example, MeshRenderer with a material that has a Texture on it), then the Async load causes a 0.02s delay.
    It seems from my testing, it only happens on textures that are above about 4MB internal size. (ie after Unity asset compression etc). It doesn't seem to matter how many textures or different images/shaders are in the scene to load, it's always about 0.02s delay.

    I can get rid of the delay if I do similar to the TextMeshPro and reference the texture in the calling scene, but that would have to be done for each texture I have, which is lots, and would actually cause more of a delay in the game load, and use up lots of memory. I'm also not sure of what this 'cache' or fix is actually doing, and if I start doing lots of these is there a limit to the amount of textures it will 'fix'.

    I had a similar problem with LoadAssetAsync() back in Feb 2018, loading textures, and I reported it to support, and all I got was a reply saying it was a 'duplicate' and they linked me to a support ticket that has been around since 2016 and not fixed yet.

    This is the 2016 report: https://issuetracker.unity3d.com/issues/async-load-is-not-async

    So they don't seem to want to fix this problem, which to me is strange, as surely frame rate drops must be pretty important.

    So, my question is, has anyone else seen this or can think of anything to stop it happening?

    My only thought was to write my own threaded raw PNG load, and then create my own textures internally with Yields stuck everywhere (However, since I don't actually know what the delay is, I have no idea if this will also introduce the same delay at some point because it's basically doing what the LoadSceneAsync() is doing) . This would be my last resort and to be honest it would probably require too much of my time at this point to be worth it.

    To me, if Async isn't Async the command isn't working and is pretty useless :(
     
  2. QFSW

    QFSW

    Joined:
    Mar 24, 2015
    Posts:
    2,905
    The point of that command is so you can have some kind of loading zone or whatnot whilst loading the new scene, not for buttery smooth streaming
     
  3. Robdon

    Robdon

    Joined:
    Jan 10, 2014
    Posts:
    141
    Hmmm, surely that is the whole point of Async loading something, to remove any frame rate drops?

    I've been in computing for a long time, and I've never heard of Async not being asynchronous.

    Maybe the command needs to be renamed to LoadNearlyAsync() .... ;)
     
  4. QFSW

    QFSW

    Joined:
    Mar 24, 2015
    Posts:
    2,905
    No its not to remove 'any frame drops' , it's so that it doesn't block the main thread and freeze the game
     
  5. Robdon

    Robdon

    Joined:
    Jan 10, 2014
    Posts:
    141
    But that is what I'm saying, it does block the main thread and freeze the game.

    Not for the full load, but for certain parts of it.
     
  6. QFSW

    QFSW

    Joined:
    Mar 24, 2015
    Posts:
    2,905
    yeah I didn't word it properly. I didn't mean it doesn't block it at all, but I guess its more akin to using a coroutine, you stop the game from locking up but you dont actually get higher performance
     
  7. TitanUnity

    TitanUnity

    Joined:
    May 15, 2014
    Posts:
    180
    We're experiencing a similar stuttering issue when calling LoadAssetsAsync when getting assets out of assetbundles, just posted thread here:
     
  8. Robdon

    Robdon

    Joined:
    Jan 10, 2014
    Posts:
    141
    I would check all your Awake() and OnEnable() routines for each GO that is in the scene you are loading. This is where I fixed most of the spikes.

    I also tried to limit the amount of GOs that had Awake() on, because I found that having lots of them called was causing a slight spike. Even if the actual code in the Awake wasn't doing much. Generally I was doing quite a bit of caching of Components<> in Awake, and I changed that so that the were Public vars and I could link them in the inspector so there were pre-assigned and I didn't need to have so many Awakes then. This helped remove most my problems.

    After reading your other thread and what the Unity guy said about the 'integration' step, I put 'progress' in my logging, and I can see that the PNG/Texture spike is during the integration step (There are no scripts on any of the GOs in my test, so its nothing in my code that is doing it), but the TextMeshPro spike is actually 1 frame after the LoadSceneAsync() finished.

    Looking in the profiler, the TextMeshPro GO is doing both an Awake and OnEnable (and also some GC Allocs) and that is where the time is, but obviously I dont know what is going on in there and cant change that myself. But, if I do the preload of a TMP GO first, it 'fixes' that spike, so I'm not too worried about that one.

    Profiling the Texture spike doesn't give me much. The 'spike' seems to be in Gfx.WaitForPresent (The spike is about x2 the amount of time WaitForPresent is taking on every other frame), which I believe is the CPU waiting for GPU... but what it's waiting for I'm not sure. Maybe its loading the texture to the GPU and that is where the spike is.
     
    Last edited: Jun 10, 2018