Something is terribly wrong with UnityWebRequest progress capture (WebGL in Editor 5.4b15)

Hi Unity folks,

I’m trying to implement some basic WWW operations to get asset bundles from remote server while displaying download progress and I can’t make it working. Build target: WebGL, Editor mode.

As per the doc the usual way to go is to yield return unityWebRequest.Send() (let’s say unityWebRequest is UnityWebRequest instance) method however it’s useless if you need to do something while Unity is working on HTTP request.

If we need to hang on in a loop we have to fire Send() and then check some condition that could tell us whether request is finished or it’s not to break the loop. However it’s not so easy to figure out such condition. UnityWebRequest attributes responsible for that are becoming lunatic and completely useless.

So what do we have here:

  1. unityWebRequest.isDone
  2. unityWebRequest.Send().isDone (AsyncOperation returned from Send)
  3. DownloadHandlerAssetBundle.isDone
  4. unityWebRequest.progress != 1.0f (using approximate equality algo)
  5. unityWebRequest.Send().downloadProgress != 1.0f

It appeared that all of them are unreliable and cannot be used for polling loop:

  1. unityWebRequest.isDone
        Debug.Log(">>>> WWWIsDone started");

        this.www = UnityWebRequest.GetAssetBundle(URL);

        Debug.Log("Before sending ...");
        this.www.Send();
        Debug.Log("Done");

//        while (www.downloadProgress < 1.0f)
        while (!www.isDone)
        {
            Debug.Log("Inside waiting loop, updating progress");
            Debug.Log(www.downloadProgress);
            Debug.Log(www.isDone);
            this.sliderProgressWWW.value = www.downloadProgress;
            yield return new WaitForEndOfFrame();
        }

        DownloadHandlerAssetBundle assetHandler = (DownloadHandlerAssetBundle)this.www.downloadHandler;

        if (assetHandler.assetBundle == null)
        {
            Debug.LogError("assetBundle is null!");
        }
        else
        {
            Debug.Log(string.Join("\n", assetHandler.assetBundle.GetAllAssetNames()));
            assetHandler.assetBundle.Unload(true);
        }

        Debug.Log("<<<< WWWIsDone finished");

It logs 0, False, then some small value like 0.04161367, False then boom! Loop’s done (isDone is true) but asset bundle is null. Not quite sure what’s happening.

If I add 2-3 seconds delay asset bundle becomes valid and fully loaded so isDone isn’t reflecting actual readiness here.

Ok keep moving.

  1. unityWebRequest.Send().isDone (AsyncOperation returned from Send)
        Debug.Log(">>>> AsyncOpIsDone started");

        this.www = UnityWebRequest.GetAssetBundle(URL);

        Debug.Log("Before sending ...");
        AsyncOperation ao = this.www.Send();
        Debug.Log("Done");

        while (!ao.isDone)
        {
            Debug.Log("Inside waiting loop, updating progress");
            this.sliderProgressWWW.value = www.downloadProgress;
            this.sliderProgressAsyncOp.value = ao.progress;
            Debug.Log(www.downloadProgress);
            Debug.Log(www.isDone);
            Debug.Log(ao.progress);
            Debug.Log(ao.isDone);
            yield return new WaitForEndOfFrame();
        }

        DownloadHandlerAssetBundle assetHandler = (DownloadHandlerAssetBundle)this.www.downloadHandler;

        if (assetHandler.assetBundle == null)
        {
            Debug.LogError("assetBundle is null!");
        }
        else
        {
            Debug.Log(string.Join("\n", assetHandler.assetBundle.GetAllAssetNames()));
            assetHandler.assetBundle.Unload(true);
        }

        Debug.Log("<<<< AsyncOpIsDone finished");

Exactly the same like in case 1, AsyncOperation.isDone is working in the same weird way as UnityWebRequest.isDone does, couple of frames with progress going up and finally isDone = true, asset bundle is null…

Nvm more to go.

  1. DownloadHandlerAssetBundle.isDone
        Debug.Log(">>>> HandlerIsDone started");

        this.www = UnityWebRequest.GetAssetBundle(URL);
        DownloadHandlerAssetBundle assetHandler = (DownloadHandlerAssetBundle)this.www.downloadHandler;

        Debug.Log("Before sending ...");
        this.www.Send();
        Debug.Log("Done");

        while (!assetHandler.isDone)
        {
            Debug.Log("Inside waiting loop, updating progress");
            this.sliderProgressWWW.value = www.downloadProgress;
            Debug.Log(www.downloadProgress);
            Debug.Log(www.isDone);
            yield return new WaitForEndOfFrame();
        }

        if (assetHandler.assetBundle == null)
        {
            Debug.LogError("assetBundle is null!");
        }
        else
        {
            Debug.Log(string.Join("\n", assetHandler.assetBundle.GetAllAssetNames()));
            assetHandler.assetBundle.Unload(true);
        }

        Debug.Log("<<<< HandlerIsDone finished");

The weirdest one, just infinite loop. Download handler never reaches isDone being true (which is out of sync with actual bundle being available with 2-3 sec delay).

4+5. progress != 1.0f

Case 2 but with the following condition:

        while (www.downloadProgress < 1.0f)

Output is curious:
Frame 1: UWR.downloadProgress: 0, UWR.isDone: false, AO.progress: 0, AO.isDone: false
Frame 2: UWR.downloadProgress: 0.06242051, UWR.isDone: false, AO.progress: 0.08322734, AO.isDone: false
Frame 3: UWR.downloadProgress: 0.4993641, UWR.isDone: true, AO.progress: 1, AO.isDone: true
Frame 4: UWR.downloadProgress: 0.8530803, UWR.isDone: true, AO.progress: 1, AO.isDone: true
Frame 5: UWR.downloadProgress: 0 (!!!), UWR.isDone: true, AO.progress: 1, AO.isDone: true

What… 0 then 0.5 then isDone is true, then back to 0.

As a conclusion the only viable solution would be checking UWR.downloadProgress whether it got up from 0 to some value and then back to 0, this is enough to say asset bundle is ready and isn’t null!

Attaching project.

Shall I submit this as a bug?

Such behavior basically contradicts documentation here.

Thanks.

2623759–184291–UnityWebRequestDemo.zip (36.9 KB)

1 Like

Hi!

This is a bug. We have a fix for it and created a regression test.
Unfortunately we could not validate your project as the bundle data is no longer accessible.

Bugreport with a self-contained reproprojects is always welcome as it helps to notify you about the fix status, adjust priorities and track similar cases.

@alexeyzakharov Do you know when the fix will be available?