Search Unity

How to check if downloadable content has changed

Discussion in 'Addressables' started by TheFudge, Jan 29, 2019.

  1. TheFudge

    TheFudge

    Joined:
    Apr 28, 2014
    Posts:
    39
    Hello,

    is there a way to determine whether the content you want to download is already cached on the device (ios, android) or if the user has to download the files [again], because there has been a content update, or the app was opened the first time?

    We have an animation module in our game and not everyone needs the data that would be neccesary for this module, but we would like to display the download button only once.

    The only thing I found was Caching.currentCacheForWriting.valid, but that only shows me when the cache is usable right?

    We are using Unity 2018.2 and Addressables 0.5.3.

    Regards,

    TheFudge
     
    noxxomatik, MNNoxMortem and Tarrag like this.
  2. TheFudge

    TheFudge

    Joined:
    Apr 28, 2014
    Posts:
    39
    I only found a very hacky solution. And it will probably not work for most of other projects.

    We only have one big download at the start. If it were different, this solution will not work.

    So at first, we download a non packed, non cached ContentVersion file. This contains a value "Version", that we will increase, if we do a content update. So this would be currently at 0.1.
    (Default value on first startup is 0.0, so we would need to download something.)

    If we figured out that we should have the current version, we check the Caching size that we got after the last download.

    Code (CSharp):
    1. // Download
    2. // Clear the cache before downloading or this wont work.
    3. Caching.ClearCache();
    4.  
    5. // Redownload everything.
    6. Addressables.PreloadDependencies<object>("animation", (info) => {
    7.     if(info.IsDone)
    8.     {
    9.         // Save size of download.
    10.         PersistentSetting.CacheSize = Mathf.FloorToInt(Caching.currentCacheForWriting.spaceOccupied / (float) (1024 * 1024));
    11.     }
    12. });

    We compare that value to the current Cache size:

    Code (CSharp):
    1. if(Caching.currentCacheForWriting.spaceOccupied / (float) (1024 * 1024) < PersistentSetting.CacheSize)
    2. {
    3.   StartDownload();
    4. }
    This will not work, if you cache something elsewhere, or you wou'll need a seperate cache for your other stuff.

    Also pretty weird: Why does the download Progress start at 50%?

    Hope it helps someone :)
     
  3. unity_bill

    unity_bill

    Joined:
    Apr 11, 2017
    Posts:
    1,053
    Our next release should have an API for checking download size. It'll take into account anything already downloaded and cached.
     
    noxxomatik likes this.
  4. TheFudge

    TheFudge

    Joined:
    Apr 28, 2014
    Posts:
    39
    That's great, exactly what we would need.

    So if I did download everything (and it's up to date) i would get a download size of 0? Or will it a bollean value like isCached or DownloadNeeded?

    And I still get different download percentages.

    On android it starts either at 66% or 50% and is finished at about 96%. In the WinEditor it's always 50% and stops at 100%. How is the PercentComplete value calculated? I guess it is not the download, but a more complex process?
     
  5. unity_bill

    unity_bill

    Joined:
    Apr 11, 2017
    Posts:
    1,053
    yes.

    two things.
    1. our % complete is a load completion, not download only. So if say, half your stuff was local, and half remote, you'd probably jump to 50% really quick (perhaps "instantly").
    2. Files are loaded differently on android than windows. There are different interfaces (and more layers of providers) on android that would lead to inconsistent numbers. I'd think it should eventually get to 100% though, so that aspect may be a bug.
     
    TheFudge likes this.
  6. TheFudge

    TheFudge

    Joined:
    Apr 28, 2014
    Posts:
    39
    Thanks for the clarification.

    So I'll have to guess where in my app the download starts?
    (I want to show the user a 0 - 100% bar, so that they wont be confused by the sudden jump or think that the app pre downloads stuff without the users permission)

    Is there some way I can achieve a download only progress by using different calls? If not, then this would be a feature request for future addressable releases :)

    Thanks for you hard work, by the way.
     
  7. unity_bill

    unity_bill

    Joined:
    Apr 11, 2017
    Posts:
    1,053
    no, we don't auto-download (or auto-load) anything. I'm just saying, you'll have an API in the next release to find out "how much download is needed", and then from there you can choose from an API to "download the stuff" or "load the stuff (which will download too)".
    so depending on which of the get (download only vs load) api's you use, the % complete may vary. If it is important to you to show the user how much is being downloaded, and the % progress, then you'd want to use the download only api first, then load later in the app as needed.
     
    MNNoxMortem and TheFudge like this.
  8. aemobile_zq

    aemobile_zq

    Joined:
    Mar 29, 2016
    Posts:
    6
    Hi bill,
    I am using the cache and assetbundle recently. I found a confusion about "Caching.currentCacheForWriting". I downloaded a assetbundle from the server and cached it, I used the latest Cache struct (I am using unity 2018.3.8f1)
    . I create the cache path and add it to caching class, it like this:
    Code (CSharp):
    1.  
    2.  protected IEnumerator LoadAssetBundleInternal(string assetBundleName, int assetType)
    3.  {
    4.     UnityWebRequest download = null;
    5.     string downloadUrl = null;
    6.  
    7.     // cache
    8.     string cachePath = string.Format("{0}/{1}", DefaultCachePath, assetBundleName);
    9.     if (!Directory.Exists(cachePath)) Directory.CreateDirectory(cachePath);
    10.     List<string> allcachePaths = new List<string>();
    11.     Caching.GetAllCachePaths(allcachePaths);
    12.     Cache currentCache;
    13.     if (allcachePaths.Contains(cachePath))
    14.     {
    15.         currentCache = Caching.GetCacheByPath(cachePath);
    16.     }
    17.     else
    18.     {
    19.         currentCache = Caching.AddCache(cachePath);
    20.     }
    21.     if (currentCache.valid)
    22.     {
    23.         currentCache.expirationDelay = GetAssetBundleExpiry(assetBundleName);
    24.         Caching.currentCacheForWriting = currentCache;
    25.     }
    26.  
    27.     //request
    28.     string hash = GetAssetBundleHash(assetBundleName);
    29.     //uint crc = GetAssetBundleCRC(assetBundleName);
    30.     downloadUrl = "my server path...";
    31.     download = UnityWebRequestAssetBundle.GetAssetBundle(downloadUrl, Hash128.Parse(hash), 0);
    32.  
    33.     yield return download.SendWebRequest();
    34.  }
    35.  
    Then when I request this method multiple times, Caching.currentCacheForWriting has a problem here: the cache directory specified by him is global! That is to say, when I download assetbundle1 and create cache path1, if assetbundle1 has not been downloaded from the server, then request assetbundle2 and create its cache path2, then when the assetbundle1 is downloaded, it will be stored in the cache path2, instead of its own cache path1.
    Is there any way to solve the problem of downloading multiple different assetbundle at the same time and putting them into their respective cache directories?

    Regards,
    aemobile_zq