I want to download all available remote asset bundles when my game initialy loads. And I cannot find API for that.
DownloadDependenciesAsync() API takes keys or labels and this is not convinient in my case.
Yes I can add some fake asset to each bundle and then request to download all of them using some label but it is a hack. What is an idiomatic way to do that?
You should be able to use Addressables.LoadContentCatalogAsync to load your remote catalog and then Addressables.GetDownloadSizeAsync to check if there’s anything to download and finally Addressables.DownloadDependenciesAsync with the result from LoadContentCatalogAsync.
Here’s a quick example of what I mean:
AsyncOperationHandle<IResourceLocator> loadContentHandle = Addressables.LoadContentCatalogAsync(catalogPath);
await loadContentHandle.Task;
AsyncOperationHandle<long> downloadSizeHandle = Addressables.GetDownloadSizeAsync(loadContentHandle.Result.Keys);
long bytes = await downloadSizeHandle.Task;
if (bytes > 0)
{
foreach (object key in loadContentHandle.Result.Keys)
{
AsyncOperationHandle downloadHandle = Addressables.DownloadDependenciesAsync(key);
while (!downloadHandle.IsDone)
{
await Task.Yield();
}
//Asset download completed, do anything with the asset
Addressables.Release(downloadHandle);
}
}
Addressables.Release(downloadSizeHandle);
Addressables.Release(loadContentHandle);
I have custom loading system. I am using label to preload a set of assets. For example I have scene Bootstrap, and according label bootstrap_preload to preload assets on that scene that have that label. @Rotary-Heart , isn’t that sufficient enough?
protected override async UniTask<bool> ExecuteAsync_Implementation(CancellationToken cancellationToken)
{
var getDownloadSizeHandle = Addressables.GetDownloadSizeAsync(_assetLabelReference);
using var getDownloadSizeReleaseHandle = getDownloadSizeHandle.ReleaseInScope();
await getDownloadSizeHandle;
if (getDownloadSizeHandle.Status == AsyncOperationStatus.Failed)
{
Debug.LogException(getDownloadSizeHandle.OperationException);
return false;
}
if (getDownloadSizeHandle.Result > 0)
{
var downloadDependenciesHandle = Addressables.DownloadDependenciesAsync(_assetLabelReference);
using var downloadDependenciesReleaseHandle = downloadDependenciesHandle.ReleaseInScope();
SetProgress01(downloadDependenciesHandle.GetDownloadStatus().Percent);
while (!downloadDependenciesHandle.IsDone)
{
await UniTask.DelayFrame(1, cancellationToken: cancellationToken);
SetProgress01(downloadDependenciesHandle.GetDownloadStatus().Percent);
}
if (downloadDependenciesHandle.Status == AsyncOperationStatus.Failed)
{
Debug.LogException(downloadDependenciesHandle.OperationException);
return false;
}
}
return true;
}
I came to similar solution. I have marked some of assets in remote bundles with “Downloadable” label and I use this label to predownload all remote bundles then. A bit ugly but works.
Oh, thank you @Rotary-Heart . My idea was to minimise amount of packages to download at login. And only then to download rest of them in background (if it’s possible).
But what you are saying is pretty interesting.
Why Addressables.LoadContentCatalogAsync has an argument for the catalog path (name)?
Isn’t a game has only one catalog for the current version?
That is the path to the catalog that you want to load, either local or remote path. No, you can have more than 1 catalog loaded, see the documentation: Addressables.LoadContentCatalogAsync | Addressables | 1.14.3 Which allows you to use a secondary catalog that holds all the remote assets that can be downloaded manually with the code above.
If you simply want to download ALL remote bundles, you can use Addressables.ResourceLocators to get all ResourceLocators, and use locator.Keys to get all keys. Finally use these keys to DownloadDependenciesAsync.
Hi @elaptop. Your code is so much interesting. Im a newbie on this addressables. Could you provide an example of this code ? isn’t this code run automatically ? or that need to be called in somewhere ?. Thanks