Search Unity

DownloadDependenciesAsync for all Asset at startup

Discussion in 'Addressables' started by ChromeCat, Feb 9, 2020.

  1. ChromeCat

    ChromeCat

    Joined:
    Jan 27, 2016
    Posts:
    35
    I've looked on forum for this answer and there were none(As far as I've looked), so I'm curious how to do it.

    I've tried serveral ways to achieve Download All Remote resources at startup. Because it's will be not appropriate for user to experience download delay everytime when try to load resource through LoadAssetAsync if there is no resource on cache.

    So far I've tried these.
    1.Get list from Addressable.InitializeAsync
    2.AfterInitializeAsync, access Addressable.ResourceLocators, get every keys, loop keys and execute Addressables.DownloadDependencyAsync(key) all of keys.

    But it seems Addressables.ResourceLocator keys has every key with local or remote. I just want the remote resources to download.

    Is there a proper way to achieve this?
     
  2. ProtoTerminator

    ProtoTerminator

    Joined:
    Nov 19, 2013
    Posts:
    586
    Will be a pain with lots of assets, but you could try putting a label on all your remote assets, and download dependencies with that label.
     
  3. ChromeCat

    ChromeCat

    Joined:
    Jan 27, 2016
    Posts:
    35
    Yeah that might be a way around. Thanks

    But there are lot of games that download on startup, and there is reason why they do that including me.

    So I thought there might be an legible practive to do it. :(

    If there is no other solution for this, then I might just label the whole things like you said.
     
  4. Prodigga

    Prodigga

    Joined:
    Apr 13, 2011
    Posts:
    1,123
    Hey I am just hitting this wall myself. We can get the download size of everything easily enough, using something like:

    Code (CSharp):
    1.         var resourceLocator = await Addressables.InitializeAsync().Task;
    2.         var allKeys = resourceLocator.Keys.ToList();
    3.         var size = await Addressables.GetDownloadSizeAsync(allKeys).Task;
    But now how do we download all of these assets and show a progress bar to show download progress? Almost every game I have seen (On mobile) follows this exact workflow. You launch the app, and it downloads the bundles while showing you the download progress. I understand I can 'not worry about it' and just load my assets asynchronously at runtime and have them be 'magically located and acquired' but really I just want to ensure all the data is available before I start the game.

    The closest I've come to this is DownloadDependenciesAsync but that doesn't seem right. I don't want to download dependancies of one key. I want to download everything right now and show the user the progress. Is there any way to do this that doesn't involve labelling everything for the single purpose of flagging them for download?
     
    Last edited: May 31, 2020
    chrismarch likes this.
  5. ProtoTerminator

    ProtoTerminator

    Joined:
    Nov 19, 2013
    Posts:
    586
    You could loop through the keys and call DownloadDependenciesAsync for each one, then use Task.WhenAll to wait for all of them. Then you'd also have to calculate the progress yourself (easy enough, just calculate the average).
    I'm not sure if this would work properly either, though, because I've seen the resourceLocator.Keys contains duplicates for each asset (address and GUID).
     
  6. Prodigga

    Prodigga

    Joined:
    Apr 13, 2011
    Posts:
    1,123
    While that works, it's not very clean and it provides no information regarding download progress and download speed. I don't really think it should be necessary for these kinds of work arounds. There should be an explicit way to prepair all assets. I understand that the idea is that the assets are managed and are located "automagically" so you shouldn't be concerned with whether they are being downloaded or loaded from disk, but this just isn't realistic. At the end of the day I need to show my players a progress bar with download percentages and file counts and sizes. What am I supposed to show the player? "Were downloading your files! I hope your ok with us downloading a mysterious amount of data right now!".
     
  7. mateuszjaworski

    mateuszjaworski

    Joined:
    Aug 8, 2019
    Posts:
    12
    Ye @Prodigga, that is actually weird. I am also looking for a better way to fetch this kind of data, but no one knows how to do it properly, unity people don't reply and documentation does not really exist... @unity_bill, @DavidUnity3d could you throw some light?
     
  8. pokruchin

    pokruchin

    Joined:
    Apr 24, 2019
    Posts:
    38
    So what is the right way of downloading all remote bundles at startup with showing the download progress if using Addressables? I can't see a clear solution right now. I'd very appreciate any help with this!
     
  9. Konomira

    Konomira

    Joined:
    Oct 11, 2015
    Posts:
    2
    I've been looking into this myself recently and I have found that the following code works to download all of the updated addressables as well as reporting progress in bytes

    Code (CSharp):
    1. using TMPro;
    2. using UnityEngine;
    3. using UnityEngine.AddressableAssets;
    4. using UnityEngine.ResourceManagement.AsyncOperations;
    5. using UnityEngine.ResourceManagement.ResourceLocations;
    6.  
    7. public class Updater : MonoBehaviour
    8. {
    9.   [SerializeField]
    10.   private TMP_Text progressLabel;
    11.   private AssetLabelReference required; // Set this to the label that all your assets use
    12.   private IList<IResourceLocation> resourceLocations;
    13.   private IEnumerator DownloadAllUpdates()
    14.   {
    15.       var loadResourceLocationsAsync = Addressables.LoadResourceLocationsAsync(required);
    16.       yield return loadResourceLocationsAsync;
    17.       resourceLocations = loadResourceLocationsAsync.Result;
    18.  
    19.       var downloadDependenciesAsync = Addressables.DownloadDependenciesAsync(resourceLocations);
    20.       var totalBytes = downloadDependenciesAsync.GetDownloadStatus().TotalBytes;
    21.  
    22.       do
    23.       {
    24.         progressLabel.text =
    25.           $"Downloading update {downloadDependenciesAsync.GetDownloadStatus().DownloadedBytes}B/{totalBytes}B";
    26.  
    27.         yield return null;
    28.       } while(!downloadDependenciesAsync.IsDone);
    29.   }
    Which does the trick, however I need to download ~2GB of assets at startup which uses 100% CPU so it grinds to a halt. I also have issues with the IsDone flag not always being set.

    I saw this post https://forum.unity.com/threads/downloaddependenciesasync-is-too-heavy.740054/ which says they're working on making it less intensive however it looks like as of Jan 25th 2021 this hasn't been implemented.
     
    Last edited: Jan 25, 2021
    doublehitgames likes this.
  10. farrukhniaztechouse0011

    farrukhniaztechouse0011

    Joined:
    Nov 22, 2021
    Posts:
    1
    Ok I've downloaded my scenes by providing labels, Now how can I load desired scene when needed...!