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 Addressables PercentCompleted or DownloadStatus not working

Discussion in 'Addressables' started by Morphus74, Mar 14, 2021.

  1. Morphus74

    Morphus74

    Joined:
    Jun 12, 2018
    Posts:
    174
    Code (CSharp):
    1. AsyncOperationHandle<SceneInstance> aoScene = sceneStarfall.LoadSceneAsync();
    2.         aoScene.Completed += result => Trace.Log($"Scene {aoScene.Result.Scene.name} successfully loaded.");
    3.  
    4.         while(!aoScene.IsDone)
    5.         {
    6.             Debug.Log($"Percent Completed {aoScene.PercentComplete} {aoScene.GetDownloadStatus().DownloadedBytes} {aoScene.GetDownloadStatus().TotalBytes} {aoScene.GetDownloadStatus().Percent}");
    7.             yield return null;
    8.         }
    PercentComplete, will go in 3 steps, since I have 3 bundles to download
    Download Status always stay at 0 for TotalBytes, Downloaded, Percent

    Are those two method still broken, as seen in many post, or I am doing something wrong?

    Unity 2020.2.7f1
    Addressable 1.16.16
     
    Last edited: Mar 14, 2021
  2. TreyK-47

    TreyK-47

    Unity Technologies

    Joined:
    Oct 22, 2019
    Posts:
    1,796
    I'll bounce this off of the team for some insight.
     
  3. Morphus74

    Morphus74

    Joined:
    Jun 12, 2018
    Posts:
    174
    Still not working with 1.17.13
     
  4. Morphus74

    Morphus74

    Joined:
    Jun 12, 2018
    Posts:
    174
    Ok maybe I am wrong but here is what I found
    Under AssetBundleProvider.cs Function BeginOperation you do
    Code (CSharp):
    1.  
    2. else if (ResourceManagerConfig.ShouldPathUseWebRequest(path))
    3.             {
    4.                 var req = CreateWebRequest(m_ProvideHandle.Location);
    5.                 req.disposeDownloadHandlerOnDispose = false;
    6.                 if (!WebRequestQueue.ShouldQueueNextRequest)
    7.                 {
    8.                     m_RequestOperation = req.SendWebRequest();
    9.                     if (m_RequestOperation.isDone)
    10.                         WebRequestOperationCompleted(m_RequestOperation);
    11.                     else
    12.                         m_RequestOperation.completed += WebRequestOperationCompleted;
    13.                 }
    14.                 else
    15.                 {
    16.                     m_WebRequestQueueOperation = WebRequestQueue.QueueRequest(req);
    17.                     if (m_WebRequestQueueOperation.IsDone)
    18.                     {
    19.                         m_RequestOperation = m_WebRequestQueueOperation.Result;
    20.                         if (m_RequestOperation.isDone)
    21.                             WebRequestOperationCompleted(m_RequestOperation);
    22.                         else
    23.                             m_RequestOperation.completed += WebRequestOperationCompleted;
    24.                     }
    25.                     else
    26.                     {
    27.                         m_WebRequestQueueOperation.OnComplete += asyncOp =>
    28.                         {
    29.                             m_RequestOperation = asyncOp;
    30.                             m_RequestOperation.completed += WebRequestOperationCompleted;
    31.                         };
    32.                     }
    33.                 }
    34.             }
    and under the same file
    Code (CSharp):
    1. DownloadStatus GetDownloadStatus()
    2.         {
    3.             if (m_Options == null)
    4.                 return default;
    5.             var status = new DownloadStatus() { TotalBytes = m_BytesToDownload, IsDone = PercentComplete() >= 1f };
    6.             if (m_BytesToDownload > 0)
    7.             {
    8.                 if (m_WebRequestQueueOperation != null && string.IsNullOrEmpty(m_WebRequestQueueOperation.m_WebRequest.error))
    9.                     m_DownloadedBytes = (long)(m_WebRequestQueueOperation.m_WebRequest.downloadedBytes);
    10.             }
    11.  
    12.             status.DownloadedBytes = m_DownloadedBytes;
    13.             return status;
    14.         }
    So you calculate the byteProgress base on m_WebRequestQueueOperation but that variable is set only in BeginOperation, and only if queue... if not you never assign it, therefore all downloaded bytes stay at 0.

    Keeping to look... see if I find a way..

    Inside GetDownloadStatus, I can get Downloaded byte from m_RequestOperation, however they are private field so not accessible without a change
     
  5. Morphus74

    Morphus74

    Joined:
    Jun 12, 2018
    Posts:
    174
    Ok... I found a solution that work for me... I modify the GetDownloadStatus in AssetBundleProvider to
    Code (CSharp):
    1.        
    2. float PercentComplete() { return m_RequestOperation != null ? m_RequestOperation.progress : 0.0f; }
    3.  
    4.         DownloadStatus GetDownloadStatus()
    5.         {
    6.             if (m_Options == null)
    7.                 return default;
    8.             var status = new DownloadStatus() { TotalBytes = m_BytesToDownload, IsDone = PercentComplete() >= 1f };
    9.             if (m_BytesToDownload > 0)
    10.             {
    11.                 if (m_WebRequestQueueOperation != null && string.IsNullOrEmpty(m_WebRequestQueueOperation.m_WebRequest.error))
    12.                     m_DownloadedBytes = (long)(m_WebRequestQueueOperation.m_WebRequest.downloadedBytes);
    13.                 else if (m_RequestOperation != null && string.IsNullOrEmpty((m_RequestOperation as UnityWebRequestAsyncOperation).webRequest.error))
    14.                    m_DownloadedBytes = (long)(m_RequestOperation as UnityWebRequestAsyncOperation).webRequest.downloadedBytes;
    15.  
    16.  
    17.             }
    18.  
    19.             status.DownloadedBytes = m_DownloadedBytes;
    20.             return status;
    21.         }
    22.  
    Two line added and now both the ASyncOperationHandle.Progress work and the DownloadStatus...
     
  6. oliviergc

    oliviergc

    Unity Technologies

    Joined:
    Dec 19, 2019
    Posts:
    26
    Hi @Morphus74

    Apologies for the delay.

    Last Friday, I tried to replicate your exact use case but it seemed to work on my end so I was about to ask you for more details.

    However, what you found seem to be correct at first sight : the downloaded bytes should be retrieved from m_RequestOperation when the request is not queued. Thanks for sharing your findings. I'll merge these changes after investigating a little more. They should be included in the next release.

    Glad it now works correctly for you. As always, don't hesitate if there's anything else.
     
  7. oliviergc

    oliviergc

    Unity Technologies

    Joined:
    Dec 19, 2019
    Posts:
    26
    For others reading this, 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
     
  8. Morphus74

    Morphus74

    Joined:
    Jun 12, 2018
    Posts:
    174
    oliviergc likes this.
  9. simbaDraco

    simbaDraco

    Joined:
    Oct 16, 2014
    Posts:
    18
    any one still having problems wioth download status here is the solution , make sure you have latest package for addressables, here is my working script:

    Code (CSharp):
    1.  private IEnumerator C_DownloadGameT(string gameName)
    2.     {
    3.    
    4.    
    5.         AsyncOperationHandle<long> firstCheck = Addressables.GetDownloadSizeAsync(gameName);
    6.         yield return firstCheck;
    7.         while (!firstCheck.IsDone)
    8.         {
    9.      
    10.         }
    11.         if (firstCheck.Status == AsyncOperationStatus.Failed)
    12.         {
    13.        
    14.             StartCoroutine(C_DownloadGameT(gameName));
    15.         }
    16.    
    17.         if(firstCheck.Status == AsyncOperationStatus.Succeeded)
    18.         {
    19.             DownloadSize = firstCheck.Result;
    20.             realSize =(float)Math.Round(DownloadSize / 1000000f,2);
    21.        
    22.         }
    23.    
    24.         if (firstCheck.Result > 0)
    25.         {
    26.             GameManager.Instance.GameState = GameState.downloading;
    27.        
    28.             AsyncOperationHandle handleCatalog = Addressables.DownloadDependenciesAsync(gameName);
    29.        
    30.             while (!handleCatalog.GetDownloadStatus().IsDone)
    31.             {
    32.                 GameManager.Instance.UI.Slider.value += (handleCatalog.GetDownloadStatus().Percent *100)/ DownloadSize;
    33.            
    34.                 GameManager.Instance.UI.TotalText.text = ((float)Math.Round(handleCatalog.GetDownloadStatus().DownloadedBytes/1000000f,2)).ToString() + "/" +realSize.ToString()+"MB";
    35.              yield return null;
    36.             }
    37.             if (handleCatalog.Status == AsyncOperationStatus.Failed)
    38.             {
    39.            
    40.                 // show internet error quit unity
    41.             }
    42.             if (handleCatalog.Status == AsyncOperationStatus.Succeeded)
    43.             {
    44.              
    45.                 LoadGameT(gameName);
    46.             }
    47.         }
    48.         else
    49.         {
    50.          
    51.        
    52.             LoadGameT(gameName);
    53.         }
    54.         yield return 0;
    55.     }
    56.  
    GetDownloadStatus() was they key function
     
  10. Morphus74

    Morphus74

    Joined:
    Jun 12, 2018
    Posts:
    174
    It work only if you have QUEUEWebRequest, not if you have DirectRequest
     
  11. Yo-Yo602

    Yo-Yo602

    Joined:
    Aug 26, 2015
    Posts:
    1
    Wow, Its Really Cool.