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

AsyncOperationHandle.PercentComplete not updating when given as a Parameter in Function

Discussion in 'Addressables' started by David_GameDev, Apr 26, 2019.

  1. ProtoTerminator

    ProtoTerminator

    Joined:
    Nov 19, 2013
    Posts:
    566
    You can access it in 1.14 now.
     
  2. tealm

    tealm

    Joined:
    Feb 4, 2014
    Posts:
    108
    PercentComplete
    is finally working for me in Addressables 1.15.1. It jumps from 0 to 0.75 in one frame though, and then continuing to slowly increment PercentComplete value while it loads the bundle. This is in a empty project where I tested the new version, with the following code:

    Code (CSharp):
    1.  
    2. private IEnumerator PreloadConfirmation()
    3. {
    4.         var downloadOperationHandle = Addressables.GetDownloadSizeAsync(label);
    5.         //...
    6.         var asyncOperationHandle = Addressables.DownloadDependenciesAsync(label);
    7.         StartCoroutine(DownloadProgress(asyncOperationHandle, downloadSizeMbytes));
    8. }
    9.  
    10. private IEnumerator DownloadProgress(AsyncOperationHandle operationHandle, float downloadSizeMBytes)
    11.         {
    12.             while (!operationHandle.IsDone)
    13.             {
    14.                 yield return null;
    15.                 if (operationHandle.Status == AsyncOperationStatus.Failed)
    16.                 {
    17.                     Debug.LogException(operationHandle.OperationException);
    18.                     yield break;
    19.                 }
    20.            
    21.                 var downloadedSizeMbComplete = operationHandle.PercentComplete * downloadSizeMBytes;
    22.                 Debug.Log($"{operationHandle.PercentComplete * 100f:F2}% ({downloadedSizeMbComplete:F2}/{downloadSizeMBytes:F2} MB)");
    23.             }
    24.        
    25.             Debug.Log("Download complete");
    26.         }
    For now I am happy that it at least works. So I am moving on, let me know if you need me to report this as a bug @unity_bill

    Using Unity 2019 LTS (2019.4.9f1)

    PS. Nice to see more documentation being added. I hope you will add example code snippets soon though, that would probably help a lot and make it less confusing to new users.

    *EDIT* Tested on both remote (AWS S3) and local server (localhost). Play mode set to Use Existing Build.
     
    Last edited: Aug 28, 2020
  3. hazuhiro

    hazuhiro

    Joined:
    Feb 14, 2019
    Posts:
    34
    why the progress not started from 0,
    i cant show the user how many bytes have been downloaded,
    because its not accurate, but its working its just the percentage is not accurate not even close
     
  4. tealm

    tealm

    Joined:
    Feb 4, 2014
    Posts:
    108
    @hazuhiro Yeah, I use a workaround for now though - and just lerp the percentage from its initial value as 0 to 100. Hopefully they will get this fixed soon.
     
    Lucas-Hehir likes this.
  5. hazuhiro

    hazuhiro

    Joined:
    Feb 14, 2019
    Posts:
    34
    can you show me some example sir?
     
  6. Lucas-Hehir

    Lucas-Hehir

    Joined:
    Jul 2, 2014
    Posts:
    41
    I did this exact thing as well, haha.

    @hazuhiro it would look a bit like this:

    Code (CSharp):
    1. var downloadTotal = await Addressables.GetDownloadSizeAsync(key: locations).Task;
    2.  
    3. while (!downloadOp.IsDone)
    4. {
    5.     await Task.Yield();
    6.  
    7.     var bytesDownloaded = (long)Mathf.Lerp(0, downloadTotal, downloadOp.PercentComplete);
    8.  
    9.     Debug.Log($"Bytes downloaded so far [{bytesDownloaded}]");
    10. }
     
    hazuhiro likes this.
  7. hazuhiro

    hazuhiro

    Joined:
    Feb 14, 2019
    Posts:
    34
    but still, the percent complete is not start from 0, it will jump directly around 0.8
     
  8. tealm

    tealm

    Joined:
    Feb 4, 2014
    Posts:
    108
    I just remap the values from the initial first PercentComplete (above 0).

    Code (CSharp):
    1.  
    2. var totalDownloadSizeMb = downloadSize / 1024f / 1024f;
    3. var percentComplete = 0f;
    4. var minPercentComplete = 0f;
    5.  
    6. while(!op.isDone)
    7. {
    8.      await UniTask.NextFrame();
    9.      //....
    10.      if (!(op.PercentComplete > percentComplete)) continue;
    11.          
    12.      if (minPercentComplete <= Mathf.Epsilon) minPercentComplete = op.PercentComplete;
    13.      percentComplete = (op.PercentComplete - minPercentComplete) / (1f - minPercentComplete);
    14.  
    15.      var downloadedSizeMbComplete = percentComplete * downloadSize / 1024 / 1024;
    16.      Debug.Log($"{percentComplete*100:F0}% ({downloadedSizeMbComplete:F2}/{totalDownloadSizeMb:F2} MB)");
    17. }
    18.  
    19. Debug.Log($"Download {op.Status}.");
    20.  
     
    hazuhiro and Raghavendra like this.
  9. hazuhiro

    hazuhiro

    Joined:
    Feb 14, 2019
    Posts:
    34
    this solution work, thanks sir
     
  10. tealm

    tealm

    Joined:
    Feb 4, 2014
    Posts:
    108
    I found this gem today
    op.GetDownloadStatus()
    . I couldn't find it in the documentation but it seems to work great so far - no need for calculating your own PercentComplete and/or downloaded bytes and total downloaded bytes.
     
    s4851798 and Kobald-Klaus like this.
  11. Kobald-Klaus

    Kobald-Klaus

    Joined:
    Jun 20, 2014
    Posts:
    126
    The latest update solves the problem by introducing the downloaded and total bytes! YEEHAAAA!
     
  12. tealm

    tealm

    Joined:
    Feb 4, 2014
    Posts:
    108
    Just to clarify, @Kobald-Klaus is talking about GetDownloadStatus() which was added in Addressables 1.14.2.
    • Added GetDownloadStatus method to AsyncOperationHandle. The DownloadStatus struct returned will contain the total number of bytes needed to be downloaded and the current number of bytes already downloaded. Cached AssetBundles will not be included in the count and if everything is cached, the values in the struct will be zero.
     
    Kobald-Klaus likes this.
  13. MatL

    MatL

    Joined:
    Jan 29, 2014
    Posts:
    43
    Finally, I had all sorts of issues, GetDownloadStatus is working as expected.
     
    EduardDraude likes this.
  14. simbaDraco

    simbaDraco

    Joined:
    Oct 16, 2014
    Posts:
    18
    How to use GetDownloadStatus?
     
  15. tealm

    tealm

    Joined:
    Feb 4, 2014
    Posts:
    108
    I use Unitask, but this should give you a general idea how to use it.
    I also use an IProgress
    IProgress<DownloadStatus> progress
    that I pass in as a parameter, which is used in my UI to show players updated download status.

    Code (CSharp):
    1. float opPercentComplete = 0;
    2. var opDependencies = Addressables.DownloadDependenciesAsync(key);
    3.  
    4. while (!opDependencies.IsDone)
    5. {
    6.   await UniTask.WaitForEndOfFrame();
    7.   if (opDependencies.Status == AsyncOperationStatus.Failed)
    8.   {
    9.     Debug.LogException(opDependencies.OperationException);
    10.     break;
    11.   }
    12.  
    13.   if (!(opDependencies.PercentComplete > opPercentComplete)) continue;
    14.   opPercentComplete = opDependencies.PercentComplete;
    15.   progress.Report(opDependencies.GetDownloadStatus());
    16. }
    17.  
     
  16. booferei

    booferei

    Joined:
    Sep 29, 2016
    Posts:
    20
    Also get this error.
    PercentComplete returns values starting at 0.62 and increasing to 0.74, finally snapping to 1.

    Interestingly, if I query the download size beforehand then the behavior changes.

    Code (CSharp):
    1. var getDownloadSizeHandle = Addressables.GetDownloadSizeAsync(assetKey);
    2. yield return getDownloadSizeHandle;
    After querying the download size, PercentComplete returns values beginning at 0.25 and ending at 0.51.
    An improvement? :/

    Using Unity 2018.4.29f1 with Addressables 1.16.15.
     
  17. booferei

    booferei

    Joined:
    Sep 29, 2016
    Posts:
    20
    However, GetDownloadStatus() fixes the issue for me.

    Code (CSharp):
    1. var handle = Addressables.LoadAssetAsync<MyClassType>(assetKey);
    2.  
    3. // then I can use:
    4. var status = handle.GetDownloadStatus();
    5. float progress = status.Percent;
    And it actually returns values between 0 and 1.
     
  18. realitygarage

    realitygarage

    Joined:
    Feb 17, 2017
    Posts:
    11
    I'm still seeing the same issue with package 2019.4.18 and package 1.17.2 - Any updates on a fix?
     
  19. realitygarage

    realitygarage

    Joined:
    Feb 17, 2017
    Posts:
    11
    also tried the GetDownloadStatus - same issue. I am loading the asset from the android /obb directory (not a server) and it takes 5 seconds to load, and is 0 for the 5 seconds, then jumps to 1 at the very end - I had gleaned the update loopp code from the spaceshooter example from github, and then also edited to use the GetDownLoadStatus - Any advice from Unity Foilks?
     
  20. Morphus74

    Morphus74

    Joined:
    Jun 12, 2018
    Posts:
    174
    Same issue with 2020.2.7 and addressable 1.16.16 or 1.17.6-preview
     
  21. TreyK-47

    TreyK-47

    Unity Technologies

    Joined:
    Oct 22, 2019
    Posts:
    1,796
    I'll ping the team for an update on this.
     
    timbokoppers likes this.
  22. Morphus74

    Morphus74

    Joined:
    Jun 12, 2018
    Posts:
    174
    Still not working with 1.17.13
     
  23. oliviergc

    oliviergc

    Unity Technologies

    Joined:
    Dec 19, 2019
    Posts:
    26
    Thanks @Morphus74 for bringing this to our attention. It seems like we may have missed some use cases. To others, please see this thread for more details.

    Note that there are some cases where the DownloadStatus will have 0 for the TotalBytes, Downloaded and Percent :
    - when the catalog is first retrieved in the initialization operation
    - when asset bundles are retrieved from the cache instead of being downloaded

    As always, don't hesitate if there's anything else.
     
    Last edited: Mar 23, 2021
  24. DaReign

    DaReign

    Joined:
    Apr 12, 2013
    Posts:
    78
    This guy here show how to make accurate progress bar for donloading
    . I tried and it worked like a charm :)

    But still I don't know how make progress bar for cached scene when you load them to memory not download to disk. I try to make scene loading screen but everything in documentation is so confusing and there is no tutorial for such simple thing.


    I tried
    Code (CSharp):
    1.  
    2. void Start()
    3.     {
    4.         if (levelToLoad != "") {
    5.             StartCoroutine(LoadAddresableScene());
    6.         }
    7.     }
    8.  
    9.     IEnumerator LoadAddresableScene()
    10.     {
    11.         yield return null;
    12.         AsyncOperationHandle<SceneInstance> handle = Addressables.LoadSceneAsync(_scene, LoadSceneMode.Single, true);
    13.      
    14.         while (handle.Status != AsyncOperationStatus.Succeeded)
    15.         {
    16.             print("Loading progress: " + (handle.PercentComplete * 100) + "%");
    17.             progressBarText.text = handle.PercentComplete * 100 +"%";
    18.             progressBar.fillAmount = handle.PercentComplete;
    19.             yield return null;
    20.         }
    21.     }
    22.  
    But scene is automatically loaded after a while without progress advance :)
     
  25. Morphus74

    Morphus74

    Joined:
    Jun 12, 2018
    Posts:
    174
    If you just make the fix I suggest, the DownloadStatus work well

    AssetBundleProvider.cs Line 178
    Code (CSharp):
    1.  
    2. DownloadStatus GetDownloadStatus()
    3. {
    4.     if (m_Options == null)
    5.         return default;
    6.     var status = new DownloadStatus() { TotalBytes = m_BytesToDownload, IsDone = PercentComplete() >= 1f };
    7.     if (m_BytesToDownload > 0)
    8.     {
    9.         if (m_WebRequestQueueOperation != null && string.IsNullOrEmpty(m_WebRequestQueueOperation.m_WebRequest.error))
    10.             m_DownloadedBytes = (long)(m_WebRequestQueueOperation.m_WebRequest.downloadedBytes);
    11.         else if (m_RequestOperation != null && string.IsNullOrEmpty((m_RequestOperation as UnityWebRequestAsyncOperation).webRequest.error))
    12.             m_DownloadedBytes = (long)(m_RequestOperation as UnityWebRequestAsyncOperation).webRequest.downloadedBytes;
    13.  
    14.  
    15.     }
    16.  
    17.     status.DownloadedBytes = m_DownloadedBytes;
    18.     return status;
    19. }
    The addressable team recognize that they forgot to process the m_RequestOperation in the DownloadStatus...
     
  26. nixcry

    nixcry

    Joined:
    Mar 13, 2017
    Posts:
    5
    Same for me.