Search Unity

Bug CleanBundleCache() doesn't seem to clear old assets

Discussion in 'Addressables' started by CChong_at_Infinity, May 24, 2022.

  1. CChong_at_Infinity

    CChong_at_Infinity

    Joined:
    Apr 7, 2020
    Posts:
    27
    We have a game that has remote assets on a CDN. Our builds typically have about 800MB of remote Addressable Bundles, and for this test, we opt to download all 800MB of assets on the device.

    If I were to clear the project Library folder, reimport all of the assets and make another build, rebuild the Addressables (and upload them to our CDN), and then install this build over the existing build on the device, the assets are now considered new and we can download another 800MB of assets (doubling it to a total of 1.6GB)

    This mimics what currently happens when we release updates for our game - our existing unchanged assets have new bundles, so our persistent data folder on mobile devices is just getting flooded with obsolete bundles.

    We've found that, fairly recently, the Addressables now has a CleanBundleCache() function that should, in theory, clean up old assets which are no longer in the catalog. However, it doesn't seem to work for us, and we're still stuck with 1.6GB of assets on the device.

    I am calling the CleanBundleCache after initializing the Addressables, as recommended in the docs:

    Code (CSharp):
    1. // Wait for addressables to initialise
    2. var addressableInitOp = Addressables.InitializeAsync();
    3. if (addressableInitOp.IsValid())
    4. {
    5.     while (!addressableInitOp.IsDone)
    6.         yield return Timing.WaitForOneFrame;
    7. }
    8.  
    9. var addressableCleanupOp = Addressables.CleanBundleCache();
    10. if(addressableCleanupOp.IsValid())
    11. {
    12.     while (!addressableCleanupOp.IsDone)
    13.         yield return Timing.WaitForOneFrame;
    14. }
    Am I missing a step?

    Other things to note are that this game exclusively uses the Addressables APIs for loading assets from the CDN, which means that it should satisfy the requirement "that only AssetBundles loaded through UnityWebRequest are cached."

    Thanks in advance for any help / wisdom.
     
  2. skytale

    skytale

    Joined:
    Feb 27, 2015
    Posts:
    10
    I have observed the same behavior. CleanBundleCache runs through successfully, but the size does not shrink. How did you solve the problem?
     
  3. skytale

    skytale

    Joined:
    Feb 27, 2015
    Posts:
    10
    I've now had a look at the code and am having trouble understanding how this is supposed to work at all. CleanBundleCache only checks the root directories even though the duplicates exist one level down? How is this supposed to work?

    Thank you!





     
    Last edited: Jul 31, 2023
  4. skytale

    skytale

    Joined:
    Feb 27, 2015
    Posts:
    10
    Here is my workaround for the previously explained problem, if anyone needs it. No idea if this can be done better. For me only the result matters...



    I now run the following code after retrieving the data:
    Code (CSharp):
    1.          
    2.             var resourceLocationsHandle = Addressables.LoadResourceLocationsAsync(_preloadLabel);
    3.             yield return resourceLocationsHandle;
    4.             if (resourceLocationsHandle.Status != AsyncOperationStatus.Succeeded)
    5.                 Debug.LogWarning($"LoadResourceLocations failed: {resourceLocationsHandle.OperationException.Message}");
    6.             var dependencies = GatherDependenciesFromLocations(resourceLocationsHandle.Result);
    7.             Addressables.Release(resourceLocationsHandle);
    8.             foreach (var dependency in dependencies) {
    9.                 var requestOption = dependency.Data as AssetBundleRequestOptions;
    10.                 if (requestOption == null) continue;
    11.                 if (!Caching.ClearOtherCachedVersions(requestOption.BundleName, Hash128.Parse(requestOption.Hash)))
    12.                     Debug.LogWarning($"ClearOtherCachedVersions failed for {requestOption.BundleName} {requestOption.Hash}");
    13.             }
    14.  
    From the AddressablesImpl file I copied the following:
    Code (CSharp):
    1.    
    2.         private List<IResourceLocation> GatherDependenciesFromLocations(IList<IResourceLocation> locations)
    3.         {
    4.             var locHash = new HashSet<IResourceLocation>();
    5.             foreach (var loc in locations) {
    6.                 if (loc.ResourceType == typeof(IAssetBundleResource)) {
    7.                     locHash.Add(loc);
    8.                 }
    9.  
    10.                 if (loc.HasDependencies) {
    11.                     foreach (var dep in loc.Dependencies)
    12.                         if (dep.ResourceType == typeof(IAssetBundleResource))
    13.                             locHash.Add(dep);
    14.                 }
    15.             }
    16.  
    17.             return new List<IResourceLocation>(locHash);
    18.         }
    19.