Using LoadFromCacheOrDownload causes iOS to freeze/stall

We have the below code. On Android, the code reports a smooth progress from
0 to 1. On iOS, it jumps straight from 0 to 1. This is also exhibited in
the foreground as when we load the asset bundle for the first time the
whole app freezes until the bundle successfully loads.

A couple of things to consider:

  • The problem is iOS specific. it
    works on every other platform.
    -we do not ship for
    webplayer
  • It successfully loads the assets on iOS - so definitely built
    for the platform
  • We download assets
    over the internet in this particular
    situation, so we are not loading from
    streaming assets
  • When we download, we save to a location on disk. Only after the content is 100% downloaded do we then load the bundle.
  • Said another way: WWW.LoadFromCacheOrDownload is given a local path to load the bundle from
  • Line 10 is yield
    every frame NOT every cpu cycle. So
    it is not maxing out the CPU.
  • To reiterate: The below code loads the bundle correctly - it just does not report on progress in a granular way AND the app freezes while loading the bundle

What we would prefer to see is a loading process that is smoother - allowing us to at least show a graduated progress bar or whirly gig.

Why is this? Is there anything we can to do mitigate?


var threadPriority = priority == AssetPriority.Foreground ? ThreadPriority.High : ThreadPriority.Low;
Application.backgroundLoadingPriority = threadPriority;
using (var www = WWW.LoadFromCacheOrDownload(url, 1)) {
    Trace.Log(string.Format("{0} {1} Priority: {2}", LocalPackagePath, ContainerPath, priority));
    www.threadPriority = threadPriority;
    Application.backgroundLoadingPriority = www.threadPriority;
    Trace.LogDiag(string.Format("{0} STARTING LoadFromCacheOrDownload", LocalPackagePath));
    Script.StartCoroutine(RunWWW(www));
    do
    {
        yield return 0;
        Trace.LogDiag("Progress: " + www.progress);
    } while (!www.isDone && String.IsNullOrEmpty(www.error));
    Trace.LogDiag(string.Format("{0} END LoadFromCacheOrDownload", LocalPackagePath));
    if (!String.IsNullOrEmpty(www.error) || www.assetBundle == null) {
        // we received an error loading the bundle
        // as the bundle is local, chances are the bundle is corrupted by something.
        // We delete and move on...
        Trace.LogError(string.Format("{0} Error loading bundle @ {1}: {2}", LocalPackagePath, ContainerPath, (String.IsNullOrEmpty(www.error) ? "Unknown" : www.error)));
        yield break;
    }
    Bundle = www.assetBundle;
    Bundle.name = ContainerPath;
}

… and:


private IEnumerator RunWWW(WWW www)
{
    yield return www;
}

I’ve seen a situation like this before where it was actually the server not sending the ‘Content-Length’ parameter, but only to a particular device (iOS if I remember correctly).

Odd, and completely confusing when diagnosing the problem! Might be worth either trying a different http server where you can view the headers, or getting a packet sniffer to rule this out.

I reproduced and verified the issue based on #684964. At the moment this behaviour is by design, we might however review it and see if we can change it in future! Thanks for bringing this to our attention.

Finally, this attached url fixed above issue I also faced.
https://forum.unity3d.com/threads/appname-was-compiled-with-optimization-stepping-may-behave-oddly-variables-may-not-be-available.372705/