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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Bug (Case 1346825) Addressables.DownloadDependenciesAsync doesn't detect error if internet drops

Discussion in 'Addressables' started by Peter77, Jun 30, 2021.

  1. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,454
    Unity 2019.4.20f1, Addressables 1.18.4, Android Player.

    Addressables.DownloadDependenciesAsync
    does not detect when the internet / Wi-Fi connection drops off while downloading.



    Reproduce
    1. Open attached project
    2. Switch to Android build target
    3. Open "Window > Asset Management > Addressables > Profiles" and activate "Editor Hosting"
    4. Open "Window > Asset Management > Addressables > Groups" and click "Build > New Build > Default Build Script"
    5. Click "File > Build and Run"
    6. Open "Window > Asset Management > Addressables > Hosting" and enable it
    7. In the running Android Player click the "Check for new content" button
    8. While data is being downloaded, turn off Wi-Fi

    Actual
    Addressables.DownloadDependenciesAsync
    never completes, even when you restore the internet / Wi-Fi connection.

    Expected
    The
    AsyncOperationHandle.IsDone
    returned by
    Addressables.DownloadDependenciesAsync
    equals true.
    The
    AsyncOperationHandle.Status
    returned by
    Addressables.DownloadDependenciesAsync
    equals
    AsyncOperationStatus.Failed
    .

    Notes
    I say "it should resume" in the video. Forget about that, it should return an error instead.
     

    Attached Files:

    llFlexford likes this.
  2. TTG_Brian

    TTG_Brian

    Joined:
    Jul 19, 2019
    Posts:
    2
    I think I might have identified the issue. In AssetBundleResource, when it goes to retry a web request via BeginOperation, it never resets m_WebRequestCompletedCallbackCalled, so the subsequent success or failure of that attempt is never reported. (See the fix on line 6 of the example code).
    Code (CSharp):
    1.         private void BeginOperation()
    2.         {
    3. ...
    4.             else if (loadType == LoadType.Web)
    5.             {
    6.                 m_WebRequestCompletedCallbackCalled = false;
    7.                 var req = CreateWebRequest(m_TransformedInternalId);
    8.                 req.disposeDownloadHandlerOnDispose = false;
    9.  
    10.                 m_WebRequestQueueOperation = WebRequestQueue.QueueRequest(req);
    11.                 if (m_WebRequestQueueOperation.IsDone)
    12.                 {
    13.                     m_RequestOperation = m_WebRequestQueueOperation.Result;
     
    Peter77 likes this.
  3. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,454
    Thank you for the reply.

    What Addressables version do you use? I'm using 1.18.4. In Addressables 1.18.4 the
    AssetBundleResource
    class doesn't have a
    m_WebRequestCompletedCallbackCalled
    member. The related
    BeginOperation
    code looks also slightly different:
    Code (CSharp):
    1.         private void BeginOperation()
    2.         {
    3. ...
    4.             else if (ResourceManagerConfig.ShouldPathUseWebRequest(path))
    5.             {
    6.                 var req = CreateWebRequest(path);
    7.                 req.disposeDownloadHandlerOnDispose = false;
    8.              
    9.                 m_WebRequestQueueOperation = WebRequestQueue.QueueRequest(req);
    10.                 if (m_WebRequestQueueOperation.IsDone)
    11.                 {
    12.                     m_RequestOperation = m_WebRequestQueueOperation.Result;
     
  4. TTG_Brian

    TTG_Brian

    Joined:
    Jul 19, 2019
    Posts:
    2
    This is in `1.18.9`.

    For reference, it's set as soon as it gets into the WebRequestOperationCompleted call, and used to prevent the call from being triggered multiple times. Maybe you can find the equivalent version in `1.18.4`?


    Code (CSharp):
    1.         private void WebRequestOperationCompleted(AsyncOperation op)
    2.         {
    3.             if (m_WebRequestCompletedCallbackCalled)
    4.                 return;
    5.  
    6.             m_WebRequestCompletedCallbackCalled = true;
     
    Last edited: Jul 2, 2021
  5. phobos2077

    phobos2077

    Joined:
    Feb 10, 2018
    Posts:
    350
    I think this retry behavior was fixed in later 1.18.* versions. Also in 1.19.4 there is now what seems to be a very useful feature of timeout based on last downloaded chunk received (how timeout is supposed to work for downloads). I haven't tested these much though (because we switched to using DownloadManager class and it does everything for us on OS-level, we just check status periodically). Also keep in mind that Addressables still doesn't have resume download functionality, which is important considering it can't download in background. In a mobile game, users WILL minimize/close the app during download and if you have bundles larger than 10mb - you are screwed :)
     
    Peter77 likes this.
  6. Randy_ye

    Randy_ye

    Joined:
    Nov 24, 2021
    Posts:
    1
    the same error still exit on unity 2020.3.47 with addressable 1.21.12
     
    llFlexford likes this.
  7. icaro56

    icaro56

    Joined:
    Apr 4, 2018
    Posts:
    6
    Same error on unity 2021.3.5f1 and addressables 1.19.19
     
    llFlexford likes this.
  8. llFlexford

    llFlexford

    Joined:
    Jan 21, 2022
    Posts:
    13
    The same error with addressable 1.21.14.

    Async operation will not completed never! It's critical bug. Only reload application can helps restart async operation!
    If you just start new addressable operation for this location will be returned previous broken operation. This operation executing infinity time(complete callback not called, don't change progress and download progress).
     
  9. llFlexford

    llFlexford

    Joined:
    Jan 21, 2022
    Posts:
    13
    For reproduce this bug you need:
    • use any operation: download, load or instantiate
    • your bundle must be 'remote'
    • addressables package 1.21.14
    • unity version - any, but i use 2021.3.*

    Steps:
    • start app
    • clean bundles cache(Caching.ClearCache)
    • disable internet connection
    • start your operation for 'remote' bundle
    • BUG - addressable async operation will execute infinity time without changes(progress, callback or download state)
    My assumptions about why the bug is happening:
    • AssetBundleProvider has method WebRequestOperationCompleted
    • this method check bool field m_RequestCompletedCallbackCalled at the start of method
    • 1 reason of bug it's - retry feature don't reset this flag before call 'BeginOperation()'. Need reset flag before 'BeginOperation()'
    • look at forceRetry code block (starts at 771 line in AssetBundleProvider.cs)
    • Code (CSharp):
      1. if (m_Retries == 0 && uwrResult.ShouldRetryDownloadError())
      2. {
      3.     Debug.LogFormat(message);
      4.     BeginOperation();
      5.     m_Retries++; //Will prevent us from entering an infinite loop of retrying if retry count is 0
      6.     forcedRetry = true;
      7. }
    • 2 reason of bug it's - 'm_Retries++' executed after 'BeginOperation'. Need increment counter before 'BeginOperation', else code will again recurse enter to 'forceRetry' code block.

    How fix BUG(tested in Rider debugger with evaluator):
    • before (AssetBundleProvider.cs:771)
      Code (CSharp):
      1. if (m_Retries == 0 && uwrResult.ShouldRetryDownloadError())
      2. {
      3.     Debug.LogFormat(message);
      4.     BeginOperation();
      5.     m_Retries++; //Will prevent us from entering an infinite loop of retrying if retry count is 0
      6.     forcedRetry = true;
      7. }
    • after (AssetBundleProvider.cs:771)
      Code (CSharp):
      1. if (m_Retries == 0 && uwrResult.ShouldRetryDownloadError())
      2. {
      3.     Debug.LogFormat(message);
      4.     m_Retries++; //Will prevent us from entering an infinite loop of retrying if retry count is 0
      5.     m_RequestCompletedCallbackCalled = false;
      6.     BeginOperation();
      7.     forcedRetry = true;
      8. }
     
  10. llFlexford

    llFlexford

    Joined:
    Jan 21, 2022
    Posts:
    13
    Also need fix 'm_RequestCompletedCallbackCalled' flag here:
    • before (AssetBundleProvider.cs:781)
      Code (CSharp):
      1. if (!forcedRetry)
      2. {
      3.     if (m_Retries < m_Options.RetryCount && uwrResult.ShouldRetryDownloadError())
      4.     {
      5.         m_Retries++;
      6.         Debug.LogFormat(message);
      7.         BeginOperation();
      8.     }
      9. .....
    • after(AssetBundleProvider.cs:781)
      Code (CSharp):
      1. if (!forcedRetry)
      2. {
      3.     if (m_Retries < m_Options.RetryCount && uwrResult.ShouldRetryDownloadError())
      4.     {
      5.         m_Retries++;
      6.         m_RequestCompletedCallbackCalled = false;
      7.         Debug.LogFormat(message);
      8.         BeginOperation();
      9.     }
      10. .....