initial commit

This commit is contained in:
Jo 2025-01-07 02:06:59 +01:00
parent 6715289efe
commit 788c3389af
37645 changed files with 2526849 additions and 80 deletions

View file

@ -0,0 +1,346 @@
---
uid: addressables-async-operation-handling
---
# Operations
Many tasks in the Addressables need to load or download information before they can return a result. To avoid blocking program execution, Addressables implements such tasks as asynchronous operations.
In contrast to a synchronous operation, which doesnt return control until the result is available, an asynchronous operation returns control to the calling function almost immediately. However, the results may not be available until some time in the future. When you call a function, such as [LoadAssetAsync], it doesn't return the loaded assets directly. Instead, it returns an [AsyncOperationHandle] object, which you can use to access the loaded assets when they become available.
You can use the following techniques to wait for the results of an asynchronous operation (while allowing other scripts to continue processing).
* [Coroutines and IEnumerator loops]
* [Events]
* [Tasks]
> [!NOTE]
> You can block the current thread to wait for the completion of an asynchronous operation. Doing so can introduce performance problems and frame rate hitches. See [Using operations synchronously].
## Releasing AsyncOperationHandle instances
Methods, like [LoadAssetsAsync], return [AsyncOperationHandle] instances that both provide the results of the operation and a way to release both the results and the operation object itself. You must retain the handle object for as long as you want to use the results. Depending on the situation, that might be one frame, until the end of a level, or even the lifetime of the application. Use the [Addressables.Release] function to release operation handles and any associated addressable assets.
Releasing an operation handle decrements the reference count of any assets loaded by the operation and invalidates the operation handle object itself. See [Memory management] for more information about reference counting in the Addressables system.
In cases where you dont need to use the results of an operation beyond a limited scope, you can release the handles right away. A few Addressables methods, such as [UnloadSceneAsync] allow you to automatically release the operation handle when it's complete.
If an operation is unsuccessful, you should still release the operation handle. Normally, Addressables releases any assets that it loaded during a failed operation, but releasing the handle still clears the handles instance data. Note that some functions, like [LoadAssetsAsync], which load multiple assets, give you the option to either retain any assets that it could load or to fail and release everything if any part of the load operation failed.
<a name="coroutine-operation-handling"></a>
## Coroutine- and IEnumerator-based operation handling
The [AsyncOperationHandle] implements the [IEnumerator] interface and will continue iteration until the operation is complete. In a coroutine, you can yield the operation handle to wait for the next iteration. When complete, the execution flow continues to the following statements. Recall that you can implement the [MonoBehaviour Start] function as a coroutine, which is a good way to have a GameObject load and instantiate the assets it needs.
The following script loads a Prefab as a child of its GameObject using a Start function coroutine. It yields the AsyncOperationHandle until the operation finishes and then uses the same handle to instantiate the Prefab.
[!code-cs[sample](../../Tests/Editor/DocExampleCode/LoadWithIEnumerator.cs#doc_LoadWithIEnumerator)]
<!--
```csharp
using System.Collections;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
public class LoadWithIEnumerator : MonoBehaviour
{
public string address;
AsyncOperationHandle<GameObject> opHandle;
public IEnumerator Start()
{
opHandle = Addressables.LoadAssetAsync<GameObject>(address);
// yielding when already done still waits until the next frame
// so don't yield if done.
if (!opHandle.IsDone)
yield return opHandle;
if (opHandle.Status == AsyncOperationStatus.Succeeded) {
Instantiate(opHandle.Result, transform);
} else {
Addressables.Release(opHandle);
}
}
void OnDestroy()
{
Addressables.Release(opHandle);
}
}
```
-->
Note that [Addressables.LoadAssetsAsync] is not able to be canceled once started. However, releasing the handle before it has finished will decrement the handle reference count and it will automatically release when the load is complete.
See [Coroutines] for more information.
### Grouping operations in a coroutine
You will probably encounter situations in which you want to perform several operations before moving on to the next step in your game logic. For example, you want to load a number of Prefabs and other assets before you start a level.
If the operations all load assets, you can combine them with a single call to the [Addressables.LoadAssetsAsync] function. The AsyncOperationhandle for this method works the same as [LoadAssetAsync]; you can yield the handle in a coroutine to wait until all the assets in the operation load. In addition, you can pass a callback function to LoadAssetsAsync and the operation calls that function when it finishes loading a specific asset. See [Loading multiple assets] for an example.
Another option is to use the [ResourceManager.CreateGenericGroupOperation] to create a group operation that completes when all of its members finish.
## Event-based operation handling
You can add a delegate function to the [Completed] event of an [AsyncOperationHandle]. The operation calls the delegate function when it's finished.
The following script performs the same function as the example in [Coroutine- and IEnumerator-based operation handling], but uses an event delegate instead of a coroutine.
[!code-cs[sample](../../Tests/Editor/DocExampleCode/LoadWithEvent.cs#doc_LoadWithEvent)]
<!--
```csharp
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
public class LoadWithEvent : MonoBehaviour
{
public string address;
AsyncOperationHandle<GameObject> opHandle;
void Start() {
opHandle = Addressables.LoadAssetAsync<GameObject>(address);
opHandle.Completed += Operation_Completed;
}
private void Operation_Completed(AsyncOperationHandle<GameObject> obj) {
if (obj.Status == AsyncOperationStatus.Succeeded) {
Instantiate(obj.Result, transform);
GameObject.Destroy(gameObject, 5);
} else {
Addressables.Release(obj);
}
}
void OnDestroy() {
Addressables.Release(opHandle);
}
}
```
-->
Note that the handle instance passed to the event delegate is the same as that returned by the original function call. You can use either to access the results and status of the operation and, ultimately, to release the operation handle and loaded assets.
## Task-based operation handling
The [AsyncOperationHandle] provides a [Task] object that you can use with the C# [async] and [await] keywords to sequence code that calls asynchronous functions and handles the results.
The following example loads Addressable assets using a list of keys. The differences between this task-based approach and the coroutine or event-based approaches are in the signature of the calling function, which must include the [async] keyword and the use of the [await] keyword with the operation handles Task property. The calling function, Start() in this case, suspends operation while the task finishes. Execution then resumes and the example instantiates all the loaded Prefabs (in a grid pattern).
[!code-cs[sample](../../Tests/Editor/DocExampleCode/LoadWithTask.cs#doc_LoadWithTask)]
<!--
```csharp
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
public class LoadWithTask : MonoBehaviour
{
// Label or address strings to load
public List<string> keys = new List<string>() { "characters", "animals" };
public float lifespan = 12;
// Operation handle used to load and release assets
AsyncOperationHandle<IList<GameObject>> loadHandle;
public async void Start(){
loadHandle = Addressables.LoadAssetsAsync<GameObject>(
keys, // Either a single key or a List of keys
addressable => {
// Called for every loaded asset
Debug.Log(addressable.name);
}, Addressables.MergeMode.Union, // How to combine multiple labels
false); // Whether to fail if any asset fails to load
// Wait for the operation to finish in the background
await loadHandle.Task;
// Instantiate the results
float x = 0, z = 0;
foreach (var addressable in loadHandle.Result){
if (addressable != null) {
Instantiate<GameObject>(addressable,
new Vector3(x++ * 2.0f, 0, z * 2.0f),
Quaternion.identity,
transform);
if (x > 9) {
x = 0;
z++;
}
}
}
}
private void OnDestroy() {
Addressables.Release(loadHandle); // Release all the loaded assets associated with loadHandle
}
}
```
-->
> [!IMPORTANT]
> The [AsyncOperationHandle.Task] property is not available on the Unity WebGL platform, which doesn't support multitasking.
When you use Task-based operation handling, you can use the C# [Task] class methods such as [WhenAll] to control which operations you run in parallel and which you want to run in sequence. The following example illustrates how to wait for more than one operation to finish before moving onto the next task:
[!code-cs[sample](../../Tests/Editor/DocExampleCode/LoadWithTask.cs#doc_useWhenAll)]
<!--
```csharp
// Load the Prefabs
var prefabOpHandle = Addressables.LoadAssetsAsync<GameObject>(
keys, null, Addressables.MergeMode.Union, false);
// Load a Scene additively
var sceneOpHandle = Addressables.LoadSceneAsync(nextScene, UnityEngine.SceneManagement.LoadSceneMode.Additive);
await Task.WhenAll(prefabOpHandle.Task, sceneOpHandle.Task);
```
-->
## Using operations synchronously
You can wait for an operation to finish without yielding, waiting for an event, or using `async await` by calling an operations [WaitForCompletion] method. This method blocks the current program execution thread while it waits for the operation to finish before continuing in the current scope.
Avoid calling WaitForCompletion on operations that can take a significant amount of time, such as those that must download data. Calling WaitForCompletion can cause frame hitches and interrupt UI responsiveness.
In Unity 2020.1 or earlier, Unity also waits for all other pending asynchronous operations to finish, so the delay in execution can be much longer than that required for just the single operation for which you call this method. In Unity 2020.2 or later, the performance impact can be less pronounced, at least when loading assets that have already been downloaded.
The following example loads a Prefab asset by address, waits for the operation to complete, and then instantiates the Prefab:
[!code-cs[sample](../../Tests/Editor/DocExampleCode/LoadSynchronously.cs#doc_LoadSynchronously)]
<!--
```csharp
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
public class LoadSynchronously : MonoBehaviour
{
public string address;
AsyncOperationHandle<GameObject> opHandle;
void Start() {
opHandle = Addressables.LoadAssetAsync<GameObject>(address);
opHandle.WaitForCompletion();
if (opHandle.Status == AsyncOperationStatus.Succeeded) {
Instantiate(opHandle.Result, transform);
} else {
Addressables.Release(opHandle);
}
}
void OnDestroy() {
Addressables.Release(opHandle);
}
}
```
-->
## Custom operations
To create a custom operation, extend the [AsyncOperationBase] class and override its virtual methods.
You can pass the derived operation to the [ResourceManager.StartOperation] method to start the operation and receive an [AsyncOperationHandle] struct. The [ResourceManager] registers operations started this way and shows them in the Addressables [Event Viewer].
### Executing the operation
The [ResourceManager] invokes the [AsyncOperationBase.Execute] method for your custom operation once the optional dependent operation completes.
### Completion handling
When your custom operation completes, call [AsyncOperationBase.Complete] on your custom operation object. You can call this within the [Execute] method or defer it to outside the call. AsyncOperationBase.Complete notifies the [ResourceManager] that the operation has finished. The ResourceManager invokes the associated [AsyncOperationHandle.Completed] events for the relevant instances of the custom operation.
### Terminating the operation
The [ResourceManager] invokes the [AsyncOperationBase.Destroy] method for your custom operation when the operation [AsyncOperationBase.ReferenceCount] reaches zero. The [AsyncOperationBase.ReferenceCount] is decreased when the [AsyncOperationHandle] that references it is released using [Addressables.Release] or when [AsyncOperationBase.DecrementReferenceCount] is called by a custom operation internally. [AsyncOperationBase.Destroy] is where you should release any memory or resources associated with your custom operation.
<a name="using-typed-versus-typeless-operation-handles"></a>
## Using typed versus typeless operation handles
Most [Addressables] methods that start an operation return a generic [AsyncOperationHandle\<T\>] struct, allowing type safety for the [AsyncOperationHandle.Completed] event and for the [AsyncOperationHandle.Result] object. You can also use a non-generic [AsyncOperationHandle] struct and convert between the two handle types as desired.
Note that a runtime exception occurs if you attempt to cast a non-generic handle to a generic handle of an incorrect type. For example:
[!code-cs[sample](../../Tests/Editor/DocExampleCode/OperationHandleTypes.cs#doc_ConvertTypes)]
<!--
```csharp
AsyncOperationHandle<Texture2D> textureHandle = Addressables.LoadAssetAsync<Texture2D>("mytexture");
// Convert the AsyncOperationHandle<Texture2D> to an AsyncOperationHandle:
AsyncOperationHandle nonGenericHandle = textureHandle;
// Convert the AsyncOperationHandle to an AsyncOperationHandle<Texture2D>:
AsyncOperationHandle<Texture2D> textureHandle2 = nonGenericHandle.Convert<Texture2D>();
// This will throw and exception because Texture2D is required:
AsyncOperationHandle<Texture> textureHandle3 = nonGenericHandle.Convert<Texture>();
```
-->
## Reporting operation progress
[AsyncOperationHandle] has two methods that you can use to monitor and report the progress of the operation:
* [GetDownloadStatus] returns a [DownloadStatus] struct. This struct contains information about how many bytes have been downloaded and how many bytes still need to be downloaded. The [DownloadStatus.Percent] reports the percentage of bytes downloaded.
* [AsyncOperationHandle.PercentComplete] returns an equally-weighted aggregate percentage of all the sub-operations that are complete. For example, if an operation has five sub-operations, each of them represents 20% of the total. The value doesn't factor in the amount of data that must be downloaded by the individual sub-operations.
For example, if you called [Addressables.DownloadDependenciesAsync] and five AssetBundles needed to be downloaded, GetDownloadStatus would tell you what percentage of the total number of bytes for all sub-operations had been downloaded so far. PercentComplete would tell you what percentage of the number of operations had finished, regardless of their size.
On the other hand, if you called [LoadAssetAsync], and one bundle had to be downloaded before an asset could be loaded from it, the download percentage might be misleading. The values obtained from GetDownloadStatus would reach 100% before the operation finished, because the operation had additional sub-operations to conduct. The value of PercentComplete would be 50% when the download sub-operation finished and 100% when the actual load into memory was complete.
[Addressables.DownloadDependenciesAsync]: xref:UnityEngine.AddressableAssets.Addressables.DownloadDependenciesAsync*
[Addressables.LoadAssetsAsync]: xref:UnityEngine.AddressableAssets.Addressables.LoadAssetsAsync*
[Addressables.Release]: xref:UnityEngine.AddressableAssets.Addressables.Release*
[Addressables]: xref:UnityEngine.AddressableAssets.Addressables
[async]: xref:langword_csharp_async
[AsyncOperationHandles]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle
[AsyncOperationBase.Complete]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1.Complete*
[AsyncOperationBase.Destroy]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1.Destroy*
[AsyncOperationBase.DecrementReferenceCount]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1.DecrementReferenceCount*
[AsyncOperationBase.ReferenceCount]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1.ReferenceCount*
[AsyncOperationBase.Execute]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1.Execute*
[AsyncOperationBase]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1
[AsyncOperationHandle.Completed]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle.Completed
[AsyncOperationHandle.PercentComplete]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle.PercentComplete
[AsyncOperationHandle.Result]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle.Result
[AsyncOperationHandle.Task]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle.Task
[AsyncOperationHandle]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle
[AsyncOperationHandle\<T\>]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle`1
[await]: xref:langword_csharp_await
[Completed]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle.Completed
[Coroutine- and IEnumerator-based operation handling]: #coroutine-operation-handling
[Coroutines]: xref:Coroutines
[DownloadStatus.Percent]: xref:UnityEngine.ResourceManagement.AsyncOperations.DownloadStatus.Percent
[DownloadStatus]: xref:UnityEngine.ResourceManagement.AsyncOperations.DownloadStatus
[Event Viewer]: xref:addressables-event-viewer
[Execute]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationBase`1.Execute*
[GetDownloadStatus]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle.GetDownloadStatus*
[IEnumerator]: xref:System.Collections.IEnumerator
[LoadAssetAsync]: xref:UnityEngine.AddressableAssets.Addressables.LoadAssetAsync*
[LoadAssetsAsync]: xref:UnityEngine.AddressableAssets.Addressables.LoadAssetsAsync*
[Loading multiple assets]: xref:addressables-loading-multiple-assets
[Memory management]: xref:addressables-memory-management
[MonoBehaviour Start]: https://docs.unity3d.com/ScriptReference/MonoBehaviour.Start.html
[ResourceManager.CreateGenericGroupOperation]: xref:UnityEngine.ResourceManagement.ResourceManager.CreateGenericGroupOperation*
[ResourceManager.StartOperation]: xref:UnityEngine.ResourceManagement.ResourceManager.StartOperation*
[ResourceManager]: xref:UnityEngine.ResourceManagement.ResourceManager
[Task]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle.Task
[UnloadSceneAsync]: xref:UnityEngine.AddressableAssets.Addressables.UnloadSceneAsync*
[WaitForCompletion]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle.WaitForCompletion*
[WhenAll]: https://docs.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.whenall
[Coroutines and IEnumerator loops]: #coroutine-operation-handling
[Events]: #event-based-operation-handling
[Tasks]: #task-based-operation-handling
[Using operations synchronously]: #using-operations-synchronously

View file

@ -0,0 +1,138 @@
---
uid: addressables-api-download-dependencies-async
---
# Preloading dependencies
When you distribute content remotely, you can sometimes improve perceived performance by downloading dependencies in advance of when your application needs them. For example, you can download essential content on start up the first time a player launches your game to make sure that they don't have to wait for content in the middle of game play.
<a name="download-dependencies"></a>
## Downloading dependencies
Use the [Addressables.DownloadDependenciesAsync] method to make sure that all the dependencies needed to load an Addressable key are available either in local content installed with the app or the download cache.
[!code-cs[sample](../../Tests/Editor/DocExampleCode/MiscellaneousTopics.cs#doc_Download)]
> [!TIP]
> if you have a set of assets that you want to pre-download, you can assign the same label, such as "preload", to the assets and use that label as the key when calling [Addressables.DownloadDependenciesAsync]. Addressables downloads all the AssetBundles containing an asset with that label if not already available (along with any bundles containing the assets' dependencies).
## Progress
An [AsyncOperationHandle] instance provides two ways to get progress:
* [AsyncOperationHandle.PercentComplete]\: reports the percentage of sub-operations that have finished. For example, if an operation uses six sub-operations to perform its task, the `PercentComplete` indicates the entire operation is 50% complete when three of those operations have finished (it doesn't matter how much data each operation loads).
* [AsyncOperationHandle.GetDownloadStatus]: returns a [DownloadStatus] struct that reports the percentage in terms of total download size. For example, if an operation has six sub-operations, but the first operation represented 50% of the total download size, then `GetDownloadStatus` indicates the operation is 50% complete when the first operation finishes.
The following example illustrates how you could use [GetDownloadStatus] to check the status and dispatch progress events during the download:
[!code-cs[sample](../../Tests/Editor/DocExampleCode/PreloadWithProgress.cs#doc_Preload)]
<!--
```csharp
using System.Collections;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.Events;
using UnityEngine.ResourceManagement.AsyncOperations;
public class PreloadWithProgress : MonoBehaviour
{
public string preloadLabel = "preload";
public UnityEvent<float> ProgressEvent;
public UnityEvent<bool> CompletionEvent;
private AsyncOperationHandle downloadHandle;
IEnumerator Start() {
downloadHandle = Addressables.DownloadDependenciesAsync(preloadLabel, false);
float progress = 0;
while (downloadHandle.Status == AsyncOperationStatus.None) {
float percentageComplete = downloadHandle.GetDownloadStatus().Percent;
if (percentageComplete > progress * 1.1) // Report at most every 10% or so
{
progress = percentageComplete; // More accurate %
ProgressEvent.Invoke(progress);
}
yield return null;
}
CompletionEvent.Invoke(downloadHandle.Status == AsyncOperationStatus.Succeeded);
Addressables.Release(downloadHandle); //Release the operation handle
}
}
```
-->
To discover how much data you need to download in order to load one or more assets, you can call [Addressables.GetDownloadSizeAsync]:
[!code-cs[sample](../../Tests/Editor/DocExampleCode/PreloadWithProgress.cs#doc_DownloadSize)]
<!--
```csharp
AsyncOperationHandle<long> getDownloadSize =
Addressables.GetDownloadSizeAsync(key);
```
-->
The Result of the completed operation is the number of bytes that must be downloaded. If Addressables has already cached all the required AssetBundles, then Result is zero.
Always release the download operation handle after you have read the Result object. If you don't need to access the results of the download operation, you can automatically release the handle by setting the `autoReleaseHandle` parameter to true, as shown in the following example:
[!code-cs[sample](../../Tests/Editor/DocExampleCode/Preload.cs#doc_Preload)]
<!--
```csharp
using System.Collections;
using UnityEngine;
using UnityEngine.AddressableAssets;
public class Preload : MonoBehaviour
{
public IEnumerator Start()
{
yield return Addressables.DownloadDependenciesAsync("preload", true);
}
}
```
-->
### Clearing the dependency cache
If you want to clear any AssetBundles cached by Addressables, call [Addressables.ClearDependencyCacheAsync]. This function clears the cached AssetBundles containing the assets identified by a key along with any bundles containing those assets' dependencies.
Note that ClearDependencyCacheAsync only clears assets bundles related to the specified key. If you updated the content catalog such that the key no longer exists or it no longer depends on the same AssetBundles, then these no-longer-referenced bundles remain in the cache until they expire (based on [cache settings]).
To clear all AssetBundles, you can use functions in the [UnityEngine.Caching] class.
[Addressables.ClearDependencyCacheAsync]: xref:UnityEngine.AddressableAssets.Addressables.ClearDependencyCacheAsync*
[Addressables.DownloadDependenciesAsync]: xref:UnityEngine.AddressableAssets.Addressables.DownloadDependenciesAsync*
[Addressables.GetDownloadSizeAsync]: xref:UnityEngine.AddressableAssets.Addressables.GetDownloadSizeAsync*
[Addressables]: xref:UnityEngine.AddressableAssets.Addressables
[AssetReference]: xref:UnityEngine.AddressableAssets.AssetReference
[AssetReferences]: xref:addressables-asset-references
[AsyncOperation.priority]: xref:UnityEngine.AsyncOperation.priority
[cache settings]: xref:UnityEngine.Cache
[Check Duplicate Bundle Dependencies]: AnalyzeTool.md#check-duplicate-bundle-dependencies
[GetDownloadStatus]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle.GetDownloadStatus*
[IResourceLocation]: xref:UnityEngine.ResourceManagement.ResourceLocations.IResourceLocation
[LoadAssetAsync]: xref:UnityEngine.AddressableAssets.Addressables.LoadAssetAsync*
[LoadAssetsAsync]: xref:UnityEngine.AddressableAssets.Addressables.LoadAssetsAsync*
[LoadResourceLocationsAsync]: xref:UnityEngine.AddressableAssets.Addressables.LoadResourceLocationsAsync*
[LoadSceneMode.Single]: xref:UnityEngine.SceneManagement.LoadSceneMode.Single
[UnityEngine.Caching]: xref:UnityEngine.Caching
[ResourceManager.ExceptionHandler]: xref:UnityEngine.ResourceManagement.ResourceManager.ExceptionHandler
[Log Runtime Exceptions]: xref:addressables-asset-settings#diagnostics
[Console]: xref:Console
[Object.Instantiate]: xref:UnityEngine.Instantiate
[Completed]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle.Completed
[AsyncOperation.allowSceneActivation]: xref:UnityEngine.AsyncOperation.allowSceneActivation
[SceneInstance]: xref:UnityEngine.ResourceManagement.ResourceProviders.SceneInstance
[LoadSceneAsync]: xref:UnityEngine.SceneManagement.SceneManager.LoadSceneAsync
[Resources.UnloadAllAssets]: xref:UnityEngine.Resources.UnloadAllAssets
[UnloadAsset]: xref:UnityEngine.Resources.UnloadAsset
[Addressables.InstantiateAsync]: xref:UnityEngine.AddressableAssets.Addressables.InstantiateAsync*
[AsyncOperationHandle]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle
[AsyncOperationHandle.GetDownloadStatus]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle.GetDownloadStatus
[AsyncOperationHandle.PercentComplete]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle.PercentComplete
[DownloadStatus]: xref:UnityEngine.ResourceManagement.AsyncOperations.DownloadStatus
[GetDownloadStatus]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle.GetDownloadStatus

View file

@ -0,0 +1,74 @@
---
uid: addressables-get-address
---
# Getting addresses at runtime
By default, Addressables uses the address you assign to an asset as the [PrimaryKey] value of its [IResourceLocation] instance. (If you disable the __[Include Addresses in Catalog]__ option of the Addressables group to which the asset belongs, the PrimaryKey could be a GUID, label, or an empty string.) If you want to get the address of an asset that you load with an AssetReference or label, you can first load the asset's locations, as described in [Loading Assets by Location]. You can then use the IResourceLocation instance to both access the PrimaryKey value and to load the asset.
The following example gets the address of the asset assigned to an [AssetReference] object named `MyRef1`:
[!code-cs[sample](../../Tests/Editor/DocExampleCode/MiscellaneousTopics.cs#doc_AddressFromReference)]
<!--
```csharp
var opHandle = Addressables.LoadResourceLocationsAsync(MyRef1);
yield return opHandle;
if (op.Status == AsyncOperationStatus.Succeeded &&
opHandle.Result != null &&
opHandle.Result.Count > 0)
{
Debug.Log("address is: " + opHandle.Result[0].PrimaryKey);
}
```
-->
Labels often refer to multiple assets. The following example illustrates how to load multiple Prefab assets and use their primary key value to add them to a dictionary:
[!code-cs[sample](../../Tests/Editor/DocExampleCode/MiscellaneousTopics.cs#doc_PreloadHazards)]
<!--
```csharp
Dictionary<string, GameObject> _preloadedObjects = new Dictionary<string, GameObject>();
private IEnumerator PreloadHazards()
{
//find all the locations with label "SpaceHazards"
var loadResourceLocationsHandle = Addressables.LoadResourceLocationsAsync("SpaceHazards", typeof(GameObject));
if( !loadResourceLocationsHandle.IsDone )
yield return loadResourceLocationsHandle;
//start each location loading
List<AsyncOperationHandle> opList = new List<AsyncOperationHandle>();
foreach (IResourceLocation location in loadResourceLocationsHandle.Result)
{
AsyncOperationHandle<GameObject> loadAssetHandle = Addressables.LoadAssetAsync<GameObject>(location);
loadAssetHandle.Completed += obj => { _preloadedObjects.Add(location.PrimaryKey, obj.Result); };
opList.Add(loadAssetHandle);
}
//create a GroupOperation to wait on all the above loads at once.
var groupOp = Addressables.ResourceManager.CreateGenericGroupOperation(opList);
if( !groupOp.IsDone )
yield return groupOp;
Addressables.Release(loadResourceLocationsHandle);
//take a gander at our results.
foreach (var item in _preloadedObjects)
{
Debug.Log(item.Key + " - " + item.Value.name);
}
}
```
-->
[Include Addresses in Catalog]: xref:addressables-content-packing-and-loading-schema#build-and-load-paths
[IResourceLocation]: xref:UnityEngine.ResourceManagement.ResourceLocations.IResourceLocation
[Loading Assets by Location]: xref:addressables-api-load-asset-async#loading-assets-by-location
[PrimaryKey]: xref:UnityEngine.ResourceManagement.ResourceLocations.IResourceLocation.PrimaryKey
[AssetReference]: xref:UnityEngine.AddressableAssets.AssetReference

View file

@ -0,0 +1,90 @@
---
uid: addressables-api-initialize-async
---
# Addressables Initialization
The Addressables system initializes itself at runtime the first time you load an Addressable or make another call to an Addressable API. Call [Addressables.InitializeAsync] to initialize Addressables earlier (this function does nothing if initialization has already occurred).
The initialization operation performs the following tasks:
* Sets up the [ResourceManager] and the [ResourceLocators].
* Loads configuration data created by Addressables from StreamingAssets.
* Executes any [initialization object] operations.
* Loads the content catalog. By default, Addressables first checks for updates to the content catalog and downloads a new catalog if available.
The following Addressables settings can change initialization behavior:
* [Only update catalogs manually]: Addressables won't automatically check for an updated catalog. See [Updating catalogs] for information about manually updating your catalogs.
* [Build Remote Catalog]: Addressables won't attempt to load remote content without a remote catalog.
* [Custom certificate handler]: identify a custom certificate handler if you need one to access your remote asset hosting service.
* [Initialization object list]: add [IObjectInitializationDataProvider] ScriptableObjects to your application that are invoked during the initialization operation.
The following runtime properties should be set before the initialization operation starts:
* [Custom URL transform function]
* [ResourceManager exception handler]
* Static properties used for any custom runtime placeholders in your [Profile variables]
### Initialization objects
You can attach objects to the Addressable Assets settings and pass them to the initialization process at runtime. For example, you can create a [CacheInitializationSettings] object to initialize Unity's [Cache] settings at runtime. To create your own types of initialization object, create a ScriptableObject that implements the [IObjectInitializationDataProvider] interface. Use this object to create the [ObjectInitializationData] asset that Addressables includes with your the runtime data.
### Cache initialization objects
Use a [CacheInitializationSettings] object to initialize Unity's [Cache] settings at runtime.
To specify the cache initialization settings that the Addressables system should use:
1. Create the CacheInitializationSettings asset (menu: __Assets > Addressables > Initialization > Cache Initialization Settings__).
2. Select the new asset file in the Project panel to view the settings in the Inspector
![](../images/addr_misc_0.png)
3. Adjust the settings as desired.
4. Open the Addressables Settings Inspector (menu: __Window > Asset Management > Addressables > Settings__).
5. In the __Initialization Objects__ section of the Inspector, click the __+__ button to add a new object to the list.
6. Select your CacheInitializationSettings asset in the File dialog and click __Open__.
7. The cache settings object is added to the list.
![](../images/addr_misc_1.png)
When Addressables initializes at runtime, it applies these settings to the default Unity [Cache]. The settings apply to all AssetBundles in the default cache, not just those downloaded by the Addressables system. See [Caching] for more information about the Unity cache system.
> [!NOTE]
> Android applications built with Unity 202.1 or earlier or running on Android 9 or earlier can only play videos from uncompressed AssetBundles. You can use a `CacheInitializationSettings` object to disable recompression of the cache by disabling the __Compress Bundles__ option.
[Addressables.CheckForCatalogUpdates]: xref:UnityEngine.AddressableAssets.Addressables.CheckForCatalogUpdates*
[Addressables.InitializeAsync]: xref:UnityEngine.AddressableAssets.Addressables.InitializeAsync*
[Addressables.LoadContentCatalogAsync]: xref:UnityEngine.AddressableAssets.Addressables.LoadContentCatalogAsync*
[Addressables.ResourceManager]: xref:UnityEngine.AddressableAssets.Addressables.ResourceManager
[Addressables.UpdateCatalogs]: xref:UnityEngine.AddressableAssets.Addressables.UpdateCatalogs*
[Build Remote Catalog]: xref:addressables-asset-settings#catalog
[Cache]: xref:UnityEngine.Cache
[CacheInitializationSettings]: xref:UnityEditor.AddressableAssets.Settings.CacheInitializationSettings
[Caching]: xref:UnityEngine.Caching
[Catalog Download Timeout]: xref:addressables-asset-settings#downloads
[Content update builds]: xref:addressables-content-update-builds
[Custom certificate handler]: xref:addressables-asset-settings#downloads
[Custom URL transform function]: xref:addressables-api-transform-internal-id
[Customizing initialization]: #customizing-initialization
[Only update catalogs manually]: xref:addressables-asset-settings#catalog
[Getting the address of an asset at runtime]: #getting-the-address-of-an-asset-at-runtime
[initialization object list]: xref:addressables-asset-settings#initialization-object-list
[initialization object]: xref:addressables-asset-settings#initialization-object-list
[InternalId]: xref:UnityEngine.ResourceManagement.ResourceLocations.IResourceLocation.InternalId
[IObjectInitializationDataProvider]: xref:UnityEngine.ResourceManagement.Util.IObjectInitializationDataProvider
[IResourceLocation]: xref:UnityEngine.ResourceManagement.ResourceLocations.IResourceLocation
[LoadContentCatalogAsync]: xref:UnityEngine.AddressableAssets.Addressables.LoadContentCatalogAsync*
[Loading additional catalogs]: #loading-additional-catalogs
[Loading Assets by Location]: xref:addressables-api-load-asset-async#loading-assets-by-location
[Modifying resource URLs at runtime]: #modifying-resource-urls-at-runtime
[ObjectInitializationData]: xref:UnityEngine.ResourceManagement.Util.ObjectInitializationData
[PrimaryKey]: xref:UnityEngine.ResourceManagement.ResourceLocations.IResourceLocation.PrimaryKey
[Profile variable syntax]: xref:addressables-profile-variables#profile-variable-syntax
[Profile variables]: xref:addressables-profile-variables#profile-variable-syntax
[RemoteLoadPath Profile variable]: xref:addressables-profiles
[ResourceLocators]: xref:UnityEngine.AddressableAssets.ResourceLocators
[ResourceManager exception handler]: xref:UnityEngine.ResourceManagement.ResourceManager.ExceptionHandler
[ResourceManager]: xref:UnityEngine.ResourceManagement.ResourceManager
[InternalIdTransformFunc]: xref:UnityEngine.ResourceManagement.ResourceManager.InternalIdTransformFunc
[Unique Bundle Ids]: xref:addressables-content-update-builds#unique-bundle-ids-setting
[Updating catalogs]: xref:addressables-api-load-content-catalog-async#updating-catalogs

View file

@ -0,0 +1,55 @@
---
uid: addressables-instantiating
---
<a name="instantiate"></a>
## Instantiating objects from Addressables
You can load an asset, such as a Prefab, and then create an instance of it with [Instantiate]. You can also load and create an instance of an asset with [Addressables.InstantiateAsync]. The main difference between these two ways of instantiating objects is how the asset reference counts are affected.
When you use InstantiateAsync, Unity increments the reference counts of the loaded assets each time you call the method. For example, if you instantiate a Prefab five times, Unity increments the reference count for the Prefab asset and any of its dependencies by five. You can then release each instance separately as they are destroyed in the application.
When you use LoadAssetAsync and Object.Instantiate, Unity only increments the asset reference counts once, during the initial load. If you release the loaded asset (or its operation handle) and the reference count decrements to zero, then Unity unloads the asset. At this point, all the additional instantiated copies lose their subassets. The copies still exist as GameObjects in the scene, but without Meshes, Materials, or other assets that they might depend on.
Both ways are useful and you should choose based on how you organize your object code. For example, if you have a single manager object that supplies a pool of Prefab enemies to spawn into a game level, it might be most convenient to release them all at the completion of the level with a single operation handle stored in the manager class. In other situations, you might want to use InstantiateAsync to load and release assets individually.
The following example calls [InstantiateAsync] to instantiate a Prefab. The example adds a component to the instantiated GameObject that releases the asset when the GameObject is destroyed.
[!code-cs[sample](../../Tests/Editor/DocExampleCode/InstantiateAsset.cs#doc_Instantiate)]
<!--
```csharp
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
public class InstantiateFromKey : MonoBehaviour
{
public string key; // Identify the asset
void Start() {
// Load and instantiate
Addressables.InstantiateAsync(key).Completed += instantiate_Completed;
}
private void instantiate_Completed(AsyncOperationHandle<GameObject> obj) {
// Add component to release asset in GameObject OnDestroy event
obj.Result.AddComponent(typeof(SelfCleanup));
Destroy(obj.Result, 12); // Destroy to trigger release
}
}
// Releases asset (trackHandle must be true in InstantiateAsync)
public class SelfCleanup : MonoBehaviour
{
void OnDestroy() {
Addressables.ReleaseInstance(gameObject);
}
}
```
-->
When you call [InstantiateAsync] you have the same options as the [Object.Instantiate] method, and also the following additional parameters:
* __instantiationParameters__: this parameter takes a [InstantiationParameters] struct that you can use to specify the instantiation options instead of specifying them in every call to the InstantiateAsync call. This can be convenient if you use the same values for multiple instantiations.
* __trackHandle__: If true, which is the default, then the Addressables system keeps track of the operation handle for the instantiated instance. This allows you to release the asset with the [Addressables.ReleaseInstance] method. If false, then the operation handle is not tracked for you and you must store a reference to the handle returned by InstantiateAsync in order to release the instance when you destroy it.

View file

@ -0,0 +1,136 @@
---
uid: addressables-api-load-content-catalog-async
---
# Managing catalogs at runtime
By default, the Addressables system manages the catalog automatically at runtime. If you built your application with a remote catalog, the Addressables system automatically checks to see if you have uploaded a new catalog, and, if so, downloads the new version and loads it into memory.
You can load additional catalogs at runtime. For example, you could load a catalog produced by a separate, compatible project to load Addressable assets built by that project. (See [Loading Content from Multiple Projects].)
If you want to change the default catalog update behavior of the Addressables system, you can turn off the automatic check and check for updates manually. See [Updating catalogs].
## Loading additional catalogs
Use [Addressables.LoadContentCatalogAsync] to load additional content catalogs, either from your hosting service or from the local file system. All that is required is for you to supply the location of the catalog you wish to load. After the operation to load the catalog is finished, you can call any Addressables loading functions using the keys in the new catalog.
If you provide the catalog hash file at the same URL as the catalog, Addressables caches the secondary catalog. When the client application loads the catalog in the future, it only downloads a new version of the catalog if the hash changes.
> [!NOTE]
> * The hash file does need to be in the same location and have the same name as your catalog. The only difference to the path should be the extension.
> * LoadContentCatalogAsync comes with a parameter autoReleaseHandle. In order for the system to download a new remote catalog, any prior calls to LoadContentCatalogAsync that point to the catalog you're attempting to load need to be released. Otherwise, the system picks up the Content Catalog load operation from our operation cache. If the cached operation is picked up, the new remote catalog is not downloaded. If set to true, the parameter autoReleaseHandle can ensure that the operation doesn't stick around in our operation cache after completing.
Once you load a catalog, you cannot unload it. You can, however, update a loaded catalog. You must release the operation handle for the operation that loaded the catalog before updating a catalog. See [Updating catalogs] for more information.
In general, there is no reason to hold on to the operation handle after loading a catalog. You can release it automatically by setting the `autoReleaseHandle` parameter to true when loading a catalog, as shown in the following example:
[!code-cs[sample](../../Tests/Editor/DocExampleCode/MiscellaneousTopics.cs#doc_LoadAdditionalCatalog)]
<!--
```csharp
public IEnumerator Start()
{
//Load a catalog and automatically release the operation handle.
AsyncOperationHandle<IResourceLocator> handle = Addressables.LoadContentCatalogAsync("path_to_secondary_catalog", true);
yield return handle;
//...
}
```
-->
> [!NOTE]
> You can use the [Catalog Download Timeout] property of your Addressables settings to specify a timeout for downloading catalogs.
## Updating catalogs
If the catalog hash file is available, Addressables checks the hash when loading a catalog to determine if the version at the provided URL is more recent than the cached version of the catalog. You can turn off the default catalog check, if desired, and call the [Addressables.UpdateCatalogs] function when you want to update the catalog. If you loaded a catalog manually with [LoadContentCatalogAsync], you must release the operation handle before you can update the catalog.
When you call the UpdateCatalog function, all other Addressable requests are blocked until the operation is finished. You can release the operation handle returned by UpdateCatalogs immediately after the operation finishes (or set the `autoRelease` parameter to true).
If you call UpdateCatalog without providing a list of catalogs, Addressables checks all of the currently loaded catalogs for updates.
[!code-cs[sample](../../Tests/Editor/DocExampleCode/MiscellaneousTopics.cs#doc_UpdateCatalog)]
<!--
```csharp
IEnumerator UpdateCatalogs()
{
AsyncOperationHandle<List<IResourceLocator>> updateHandle
= Addressables.UpdateCatalogs();
yield return updateHandle;
Addressables.Release(updateHandle);
}
```
-->
You can also call [Addressables.CheckForCatalogUpdates] directly to get the list of catalogs that have updates and then perform the update:
[!code-cs[sample](../../Tests/Editor/DocExampleCode/MiscellaneousTopics.cs#doc_CheckCatalog)]
<!--
```csharp
IEnumerator UpdateCatalogs()
{
List<string> catalogsToUpdate = new List<string>();
AsyncOperationHandle<List<string>> checkForUpdateHandle = Addressables.CheckForCatalogUpdates();
checkForUpdateHandle.Completed += op =>
{
catalogsToUpdate.AddRange(op.Result);
};
yield return checkForUpdateHandle;
if (catalogsToUpdate.Count > 0)
{
AsyncOperationHandle<List<IResourceLocator>> updateHandle = Addressables.UpdateCatalogs(catalogsToUpdate);
yield return updateHandle;
Addressables.Release(updateHandle);
}
Addressables.Release(checkForUpdateHandle);
}
```
-->
> [!IMPORTANT]
> If you update a catalog when you have already loaded content from the related AssetBundles, you can encounter conflicts between the loaded AssetBundles and the updated versions. You can enable the [Unique Bundle Ids] option in your Addressable settings to eliminate the possibility of bundle ID collisions at runtime. However, enabling this option also means that more AssetBundles must typically be rebuilt when you perform a content update. See [Content update builds] for more information. Another option is to first unload any content and AssetBundles that must be updated, which can be a slow operation.
[Loading Content from Multiple Projects]: xref:addressables-multiple-projects
[Addressables.CheckForCatalogUpdates]: xref:UnityEngine.AddressableAssets.Addressables.CheckForCatalogUpdates*
[Addressables.InitializeAsync]: xref:UnityEngine.AddressableAssets.Addressables.InitializeAsync*
[Addressables.LoadContentCatalogAsync]: xref:UnityEngine.AddressableAssets.Addressables.LoadContentCatalogAsync*
[Addressables.ResourceManager]: xref:UnityEngine.AddressableAssets.Addressables.ResourceManager
[Addressables.UpdateCatalogs]: xref:UnityEngine.AddressableAssets.Addressables.UpdateCatalogs*
[Build Remote Catalog]: xref:addressables-asset-settings#catalog
[Cache]: xref:UnityEngine.Cache
[CacheInitializationSettings]: xref:UnityEditor.AddressableAssets.Settings.CacheInitializationSettings
[Caching]: xref:UnityEngine.Caching
[Catalog Download Timeout]: xref:addressables-asset-settings#downloads
[Content update builds]: xref:addressables-content-update-builds
[Custom certificate handler]: xref:addressables-asset-settings#downloads
[Custom URL transform function]: #id-transform-function
[Customizing initialization]: #customizing-initialization
[Only update catalogs manually]: xref:addressables-asset-settings#catalog
[Getting the address of an asset at runtime]: #getting-the-address-of-an-asset-at-runtime
[initialization object list]: xref:addressables-asset-settings#initialization-object-list
[initialization object]: xref:addressables-asset-settings#initialization-object-list
[InternalId]: xref:UnityEngine.ResourceManagement.ResourceLocations.IResourceLocation.InternalId
[IObjectInitializationDataProvider]: xref:UnityEngine.ResourceManagement.Util.IObjectInitializationDataProvider
[IResourceLocation]: xref:UnityEngine.ResourceManagement.ResourceLocations.IResourceLocation
[LoadContentCatalogAsync]: xref:UnityEngine.AddressableAssets.Addressables.LoadContentCatalogAsync*
[Loading additional catalogs]: #loading-additional-catalogs
[Loading Assets by Location]: xref:addressables-loading-assets#loading-assets-by-location
[Modifying resource URLs at runtime]: #modifying-resource-urls-at-runtime
[ObjectInitializationData]: xref:UnityEngine.ResourceManagement.Util.ObjectInitializationData
[PrimaryKey]: xref:UnityEngine.ResourceManagement.ResourceLocations.IResourceLocation.PrimaryKey
[Profile variable syntax]: xref:addressables-profile-variables#profile-variable-syntax
[Profile variables]: xref:addressables-profile-variables#profile-variable-syntax
[RemoteLoadPath Profile variable]: xref:addressables-profiles
[ResourceLocators]: xref:UnityEngine.AddressableAssets.ResourceLocators
[ResourceManager exception handler]: xref:UnityEngine.ResourceManagement.ResourceManager.ExceptionHandler
[ResourceManager]: xref:UnityEngine.ResourceManagement.ResourceManager
[InternalIdTransformFunc]: xref:UnityEngine.ResourceManagement.ResourceManager.InternalIdTransformFunc
[Unique Bundle Ids]: xref:addressables-content-update-builds#unique-bundle-ids-setting
[Updating catalogs]: #updating-catalogs

View file

@ -0,0 +1,237 @@
---
uid: addressables-api-load-asset-async
---
# Loading Addressable assets
The [Addressables] class provides several methods for loading Addressable assets. You can load assets one at a time or in batches. To identify the assets to load, you pass either a single key or a list of keys to the loading function. A key can be one of the following objects:
* Address: a string containing the address you assigned to the asset
* Label: a string containing a label assigned to one or more assets
* AssetReference object: an instance of [AssetReference]
* [IResourceLocation] instance: an intermediate object that contains information to load an asset and its dependencies.
When you call one of the asset loading functions, the Addressables system begins an asynchronous operation that carries out the following tasks:
1. Looks up the resource locations for the specified keys (except IResourceLocation keys)
2. Gathers the list of dependencies
3. Downloads any remote AssetBundles that are required
4. Loads the AssetBundles into memory
5. Sets the [Result] object of the operation to the loaded objects
6. Updates the [Status] of the operation and calls any [Completed] event listeners
If the load operation succeeds, the Status is set to Succeeded and the loaded object or objects can be accessed from the [Result] object.
If an error occurs, the exception is copied to the [OperationException] member of the operation object and the Status is set to Failed. By default, the exception is not thrown as part of the operation. However, you can assign a handler function to the [ResourceManager.ExceptionHandler] property to handle any exceptions. Additionally, you can enable the [Log Runtime Exceptions] option in your Addressable system settings to record errors to the Unity [Console].
When you call loading functions that can load multiple Addressable assets, you can specify whether the entire operation should abort if any single load operation fails or whether the operation should load any assets it can. In both cases, the operation status is set to failed. (Set the `releaseDependenciesOnFailure` parameter to true in the call to the loading function to abort the entire operation on any failure.)
See [Operations] for more information about asynchronous operations and writing asynchronous code in Unity scripts.
### Correlating loaded assets to their keys
When you load multiple assets in one operation, the order in which individual assets are loaded is not necessarily the same as the order of the keys in the list you pass to the loading function.
If you need to associate an asset in a combined operation with the key used to load it, you can perform the operation in two steps:
1. Load the [IResourceLocation] instances with the list of asset keys.
2. Load the individual assets using their IResourceLocation instances as keys.
The IResourceLocation object contains the key information so you can, for example, keep a dictionary to correlate the key to an asset. Note that when you call a loading function, such as [LoadAssetsAsync], the operation first looks up the [IResourceLocation] instances that correspond to a key and then uses that to load the asset. When you load an asset using an IResourceLocation, the operation skips the first step. Thus, performing the operation in two steps does not add significant additional work.
The following example loads the assets for a list of keys and inserts them into a dictionary by their address ([PrimaryKey]). The example first loads the resource locations for the specified keys. When that operation is complete, it loads the asset for each location, using the Completed event to insert the individual operation handles into the dictionary. The operation handles can be used to instantiate the assets, and, when the assets are no longer needed, to release them.
[!code-cs[sample](../../Tests/Editor/DocExampleCode/LoadLocation.cs#doc_Load)]
<!--
``` csharp
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.Events;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.ResourceManagement.ResourceLocations;
public class LoadWithLocation : MonoBehaviour
{
public Dictionary<string, AsyncOperationHandle<GameObject>> operationDictionary;
public List<string> keys;
public UnityEvent Ready;
IEnumerator LoadAndAssociateResultWithKey(IList<string> keys) {
if(operationDictionary == null)
operationDictionary = new Dictionary<string, AsyncOperationHandle<GameObject>>();
AsyncOperationHandle<IList<IResourceLocation>> locations
= Addressables.LoadResourceLocationsAsync(keys,
Addressables.MergeMode.Union, typeof(GameObject));
yield return locations;
var loadOps = new List<AsyncOperationHandle>(locations.Result.Count);
foreach (IResourceLocation location in locations.Result) {
AsyncOperationHandle<GameObject> handle =
Addressables.LoadAssetAsync<GameObject>(location);
handle.Completed += obj => operationDictionary.Add(location.PrimaryKey, obj);
loadOps.Add(handle);
}
yield return Addressables.ResourceManager.CreateGenericGroupOperation(loadOps, true);
Ready.Invoke();
}
void Start() {
Ready.AddListener(OnAssetsReady);
StartCoroutine(LoadAndAssociateResultWithKey(keys));
}
private void OnAssetsReady() {
float x = 0, z = 0;
foreach (var item in operationDictionary) {
Debug.Log($"{item.Key} = {item.Value.Result.name}");
Instantiate(item.Value.Result,
new Vector3(x++ * 2.0f, 0, z * 2.0f),
Quaternion.identity, transform);
if (x > 9) {
x = 0;
z++;
}
}
}
private void OnDestroy() {
foreach(var item in operationDictionary) {
Addressables.Release(item.Value);
}
}
}
```
-->
Note that the loading function creates a group operation with [ResourceManager.CreateGenericGroupOperation]. This allows the function to continue after all the loading operations have finished. In this case, the function dispatches a "Ready" event to notify other scripts that the loaded data can be used.
## Loading assets by location
When you load an Addressable asset by address, label, or AssetReference, the Addressables system first looks up the resource locations for the assets and uses these [IResourceLocation] instances to download the required AssetBundles and any dependencies. You can perform the asset load operation in two steps by first getting the IResourceLocation objects with [LoadResourceLocationsAsync] and then using those objects as keys to load or instantiate the assets.
[IResourceLocation] objects contain the information needed to load one or more assets.
The [LoadResourceLocationsAsync] method never fails. If it cannot resolve the specified keys to the locations of any assets, it returns an empty list. You can restrict the types of asset locations returned by the function by specifying a specific type in the `type` parameter.
The following example loads locations for all assets labeled with "knight" or "villager":
[!code-cs[sample](../../Tests/Editor/DocExampleCode/LoadLocation.cs#doc_LoadLocations)]
<!--
```csharp
AsyncOperationHandle<IList<IResourceLocation>> handle
= Addressables.LoadResourceLocationsAsync(new string[]
{
"knight",
"villager"
}, Addressables.MergeMode.Union);
yield return handle;
//...
Addressables.Release(handle);
```
-->
## Loading locations of subobjects
Locations for SubObjects are generated at runtime to reduce the size of the content catalogs and improve runtime performance. When you call [LoadResourceLocationsAsync] with the key of an asset with subobjects and don't specify a type, then the function generates IResourceLocation instances for all of the subobjects as well as the main object (if applicable). Likewise, if you do not specify which subobject to use for an AssetReference that points to an asset with subobjects, then the system generates IResourceLocations for every subobject.
For example, if you load the locations for an FBX asset, with the address, "myFBXObject", you might get locations for three assets: a GameObject, a Mesh, and a Material. If, instead, you specified the type in the address, "myFBXObject[Mesh]", you would only get the Mesh object. You can also specify the type using the `type` parameter of the LoadResourceLocationsAsync function.
## Asynchronous Loading
The Addressables system API is asynchronous and returns an [AsyncOperationHandle] for use with managing operation progress and completion.
Addressables is designed to content location agnostic. The content may need to be downloaded first or use other methods that can take a long time. To force synchronous execution, See [Synchronous Addressables] for more information.
When loading an asset for the first time, the handle is done after a minimum of one frame. You can wait until the load has completed using different methods as shown below.
If the content has already been loaded, execution times may differ between the various asynchronous loading options shown below.
* [Coroutine]: Always be delayed at minimum of one frame before execution continues.
* [Completed callback]: Is a minimum of one frame if the content has not already been loaded, otherwise the callback is invoked in the same frame.
* Awaiting [AsyncOperationHandle.Task]: Is a minimum of one frame if the content has not already been loaded, otherwise the execution continues in the same frame.
[!code-cs[sample](../../Tests/Editor/DocExampleCode/AsynchronousLoading.cs#doc_asyncload)]
## Unloading Addressable assets
See [Unloading Addressables].
## Using Addressables in a Scene
If a Scene is itself Addressable, you can use Addressable assets in the scene just as you would any assets. You can place Prefabs and other assets in the Scene, assign assets to component properties, and so on. If you use an asset that is not Addressable, that asset becomes an implicit dependency of the Scene and the build system packs it in the same AssetBundle as the Scene when you make a content build. (Addressable assets are packed into their own AssetBundles according to the group they are in.)
> [!NOTE]
> Implicit dependencies used in more than one place can be duplicated in multiple AssetBundles and in the built-in scene data. Use the [Check Duplicate Bundle Dependencies] rule in the Analyze tool to find unwanted duplication of assets.
If a Scene is NOT Addressable, then any Addressable assets you add directly to the scene hierarchy become implicit dependencies and Unity includes copies of those assets in the built-in scene data even if they also exist in an Addressable group. The same is true for any assets, such as Materials, assigned to a component on a GameObject in the scene.
In custom component classes, you can use [AssetReference] fields to allow the assignment of Addressable assets in non-Addressable scenes. Otherwise, you can use [addresses] and [labels] to load assets at runtime from a script. Note that you must load an AssetReference in code whether or not the Scene is Addressable.
[ActivateAsync]: xref:UnityEngine.ResourceManagement.ResourceProviders.SceneInstance.ActivateAsync*
[Addressables.ClearDependencyCacheAsync]: xref:UnityEngine.AddressableAssets.Addressables.ClearDependencyCacheAsync*
[Addressables.DownloadDependenciesAsync]: xref:UnityEngine.AddressableAssets.Addressables.DownloadDependenciesAsync*
[Addressables.GetDownloadSizeAsync]: xref:UnityEngine.AddressableAssets.Addressables.GetDownloadSizeAsync*
[Addressables.InstantiateAsync]: xref:UnityEngine.AddressableAssets.Addressables.InstantiateAsync*
[Addressables.LoadAssetAsync]: xref:UnityEngine.AddressableAssets.Addressables.LoadAssetAsync*
[Addressables.LoadSceneAsync]: xref:UnityEngine.AddressableAssets.Addressables.LoadSceneAsync*
[Addressables.ReleaseInstance]: xref:UnityEngine.AddressableAssets.Addressables.ReleaseInstance*
[Addressables]: xref:UnityEngine.AddressableAssets.Addressables
[Application.backgroundLoadingPriority]: xref:UnityEngine.Application.backgroundLoadingPriority
[AssetReference]: xref:UnityEngine.AddressableAssets.AssetReference
[AssetReferences]: xref:addressables-asset-references
[AsyncOperation.priority]: xref:UnityEngine.AsyncOperation.priority
[cache settings]: xref:UnityEngine.Cache
[Check Duplicate Bundle Dependencies]: xref:addressables-analyze-tool#check-duplicate-bundle-dependencies
[GetDownloadStatus]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle.GetDownloadStatus*
[Instantiate]: xref:UnityEngine.Object.Instantiate*
[InstantiateAsync]: xref:UnityEngine.AddressableAssets.Addressables.InstantiateAsync*
[InstantiationParameters]: xref:UnityEngine.ResourceManagement.ResourceProviders.InstantiationParameters
[IResourceLocation]: xref:UnityEngine.ResourceManagement.ResourceLocations.IResourceLocation
[AsyncOperationHandle]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle
[AsyncOperationHandle.Task]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle.Task
[Completed callback]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle.Completed
[Coroutine]: xref:UnityEngine.Coroutine
[HideFlags.DontUnloadUnusedAsset]: xref:UnityEngine.HideFlags.DontUnloadUnusedAsset
[LoadAssetAsync]: xref:UnityEngine.AddressableAssets.Addressables.LoadAssetAsync*
[LoadAssetsAsync]: xref:UnityEngine.AddressableAssets.Addressables.LoadAssetsAsync*
[LoadResourceLocationsAsync]: xref:UnityEngine.AddressableAssets.Addressables.LoadResourceLocationsAsync*
[LoadSceneMode.Single]: xref:UnityEngine.SceneManagement.LoadSceneMode.Single
[Memory Management]: xref:addressables-memory-management
[merge mode]: xref:UnityEngine.AddressableAssets.Addressables.MergeMode
[Object.DontDestroyOnLoad]: xref:UnityEngine.Object.DontDestroyOnLoad(UnityEngine.Object)
[OperationException]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle.OperationException
[Operations]: xref:addressables-async-operation-handling
[PrimaryKey]: xref:UnityEngine.ResourceManagement.ResourceLocations.IResourceLocation.PrimaryKey
[Releasing Addressable assets]: #releasing-addressable-assets
[ResourceManager.Acquire]: xref:UnityEngine.ResourceManagement.ResourceManager.Acquire(UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle)
[ResourceManager.CreateGenericGroupOperation]: xref:UnityEngine.ResourceManagement.ResourceManager.CreateGenericGroupOperation*
[Resources.UnloadUnusedAssets]: xref:UnityEngine.Resources.UnloadUnusedAssets
[Result]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle.Result
[SceneManager.LoadSceneAsync]: xref:UnityEngine.SceneManagement.SceneManager.LoadSceneAsync(System.String,UnityEngine.SceneManagement.LoadSceneMode)
[Status]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle.Status
[UnityEngine.Caching]: xref:UnityEngine.Caching
[ResourceManager.ExceptionHandler]: xref:UnityEngine.ResourceManagement.ResourceManager.ExceptionHandler
[Log Runtime Exceptions]: xref:addressables-asset-settings#diagnostics
[Console]: xref:Console
[Object.Instantiate]: xref:UnityEngine.Object.Instantiate*
[addresses]: xref:addressables-overview#asset-addresses
[labels]: xref:addressables-labels
[Completed]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle.Completed
[AsyncOperation.allowSceneActivation]: xref:UnityEngine.AsyncOperation.allowSceneActivation
[SceneInstance]: xref:UnityEngine.ResourceManagement.ResourceProviders.SceneInstance
[LoadSceneAsync]: xref:UnityEngine.SceneManagement.SceneManager.LoadSceneAsync(System.String,UnityEngine.SceneManagement.LoadSceneMode)
[UnloadAsset]: xref:UnityEngine.Resources.UnloadAsset(UnityEngine.Object)
[Addressables.InstantiateAsync]: xref:UnityEngine.AddressableAssets.Addressables.InstantiateAsync*
[Scene loading project]: https://github.com/Unity-Technologies/Addressables-Sample/tree/master/Basic/Scene%20Loading
[Addressables-Sample]: https://github.com/Unity-Technologies/Addressables-Sample
[Synchronous Addressables]: xref:synchronous-addressables
[Unloading Addressables]: xref:addressables-unloading

View file

@ -0,0 +1,109 @@
---
uid: addressables-loading-bundles
---
# AssetBundle Loading
The Addressables system packs your assets in AssetBundles and loads these bundles "behind the scenes" as you load individual assets. You can control how AssetBundles load which are exposed on the `BundledAssetGroupSchema` class. You can set these options through the scripting API or under the Advanced options in the inspector of the `AddressablesAssetGroup` inspector.
## UnityWebRequestForLocalBundles
Addressables can load AssetBundles via two engine APIs: `UnityWebRequest.GetAssetBundle`, and `AssetBundle.LoadFromFileAsync`. The default behavior is to use `AssetBundle.LoadFromFileAsync` when the AssetBundle is in local storage and use `UnityWebRequest` when the AssetBundle path is a URL.
You can override this behavior to use `UnityWebRequest` for local Asset Bundles by setting `BundledAssetGroupSchema.UseUnityWebRequestForLocalBundles` to true. It can also be set through the BundledAssetGroupSchema GUI.
A few of these situations would include:
1. You are shipping local AssetBundles that use LZMA compression because you want your shipped game package to be as small as possible. In this case, you would want to use UnityWebRequest to recompress those AssetBundles LZ4 into the local disk cache.
2. You are shipping an Android game and your APK contains AssetBundles that are compressed with the default APK compression.
3. You want the entire local AssetBundle to be loaded into memory to avoid disk seeks. If you use `UnityWebRequest` and have caching disabled, the entire AssetBundle file will be loaded into the memory cache. This increases your runtime memory usage, but may improve loading performance as it eliminates disk seeking after the initial AssetBundle load.
Both situations 1 and 2 above result in the AssetBundle existing on the player device twice (original and cached representations). This means the initial loads (decompressing and copying to cache) are slower than subsequent loads (loading from cache)
## Handling Download Errors
When a download fails, the RemoteProviderException contains errors that can be used to determine how to handle the failure.
The RemoteProviderException is either the `AsyncOperationHandle.OperationException` or an inner exception. As shown below:
[!code-cs[sample](../../Tests/Editor/DocExampleCode/DownloadError.cs#doc_DownloadError)]
<!--
```csharp
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.ResourceManagement.Exceptions;
internal class HandleDownloadError : MonoBehaviour
{
private AsyncOperationHandle m_Handle;
void LoadAsset()
{
m_Handle = Addressables.LoadAssetAsync<GameObject>("addressKey");
m_Handle.Completed += handle =>
{
string dlError = GetDownloadError(m_Handle);
if (!string.IsNullOrEmpty(dlError))
{
// handle what error
}
};
}
string GetDownloadError(AsyncOperationHandle fromHandle)
{
if (fromHandle.Status != AsyncOperationStatus.Failed)
return null;
RemoteProviderException remoteException;
System.Exception e = fromHandle.OperationException;
while (e != null)
{
remoteException = e as RemoteProviderException;
if (remoteException != null)
return remoteException.WebRequestResult.Error;
e = e.InnerException;
}
return null;
}
}
```
-->
Possible error strings:
* "Request aborted"
* "Unable to write data"
* "Malformed URL"
* "Out of memory"
* "No Internet Connection"
* "Encountered invalid redirect (missing Location header?)"
* "Cannot modify request at this time"
* "Unsupported Protocol"
* "Destination host has an erroneous SSL certificate"
* "Unable to load SSL Cipher for verification"
* "SSL CA certificate error"
* "Unrecognized content-encoding"
* "Request already transmitted"
* "Invalid HTTP Method"
* "Header name contains invalid characters"
* "Header value contains invalid characters"
* "Cannot override system-specified headers"
* "Backend Initialization Error"
* "Cannot resolve proxy"
* "Cannot resolve destination host"
* "Cannot connect to destination host"
* "Access denied"
* "Generic/unknown HTTP error"
* "Unable to read data"
* "Request timeout"
* "Error during HTTP POST transmission"
* "Unable to complete SSL connection"
* "Redirect limit exceeded"
* "Received no data in response"
* "Destination host does not support SSL"
* "Failed to transmit data"
* "Failed to receive data"
* "Login failed"
* "SSL shutdown failed"
* "Redirect limit is invalid"
* "Not implemented"
* "Data Processing Error, see Download Handler error"
* "Unknown Error"

View file

@ -0,0 +1,108 @@
---
uid: addressables-loading-asset-reference
---
# Loading an AssetReference
The [AssetReference] class has its own load method, [LoadAssetAsync].
[!code-cs[sample](../../Tests/Editor/DocExampleCode/LoadReference.cs#doc_Load)]
<!--
``` csharp
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
public class LoadFromReference : MonoBehaviour
{
// Assign in Editor
public AssetReference reference;
// Start the load operation on start
void Start() {
AsyncOperationHandle handle = reference.LoadAssetAsync<GameObject>();
handle.Completed += Handle_Completed;
}
// Instantiate the loaded prefab on complete
private void Handle_Completed(AsyncOperationHandle obj) {
if (obj.Status == AsyncOperationStatus.Succeeded) {
Instantiate(reference.Asset, transform);
} else {
Debug.LogError("AssetReference failed to load.");
}
Destroy(gameobject, 12); // Destroy object to demonstrate release
}
// Release asset when parent object is destroyed
private void OnDestroy() {
reference.ReleaseAsset();
}
}
```
-->
You can also use the AssetReference object as a key to the [Addressables.LoadAssetAsync] methods. If you need to spawn multiple instances of the asset assigned to an AssetReference, use [Addressables.LoadAssetAsync], which gives you an operation handle that you can use to release each instance.
See [AssetReference] for more information about using AssetReferences.
[ActivateAsync]: xref:UnityEngine.ResourceManagement.ResourceProviders.SceneInstance.ActivateAsync*
[Addressables.ClearDependencyCacheAsync]: xref:UnityEngine.AddressableAssets.Addressables.ClearDependencyCacheAsync*
[Addressables.DownloadDependenciesAsync]: xref:UnityEngine.AddressableAssets.Addressables.DownloadDependenciesAsync*
[Addressables.GetDownloadSizeAsync]: xref:UnityEngine.AddressableAssets.Addressables.GetDownloadSizeAsync*
[Addressables.InstantiateAsync]: xref:UnityEngine.AddressableAssets.Addressables.InstantiateAsync*
[Addressables.LoadAssetAsync]: xref:UnityEngine.AddressableAssets.Addressables.LoadAssetAsync*
[Addressables.LoadSceneAsync]: xref:UnityEngine.AddressableAssets.Addressables.LoadSceneAsync*
[Addressables.ReleaseInstance]: xref:UnityEngine.AddressableAssets.Addressables.ReleaseInstance*
[Addressables]: xref:UnityEngine.AddressableAssets.Addressables
[Application.backgroundLoadingPriority]: xref:UnityEngine.Application.backgroundLoadingPriority
[AssetReference]: xref:UnityEngine.AddressableAssets.AssetReference
[AssetReferences]: xref:addressables-asset-references
[AsyncOperation.priority]: xref:UnityEngine.AsyncOperation.priority
[cache settings]: xref:UnityEngine.Cache
[Check Duplicate Bundle Dependencies]: AnalyzeTool.md#check-duplicate-bundle-dependencies
[GetDownloadStatus]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle.GetDownloadStatus*
[Instantiate]: xref:UnityEngine.Object.Instantiate*
[InstantiateAsync]: xref:UnityEngine.AddressableAssets.Addressables.InstantiateAsync*
[InstantiationParameters]: xref:UnityEngine.ResourceManagement.ResourceProviders.InstantiationParameters
[IResourceLocation]: xref:UnityEngine.ResourceManagement.ResourceLocations.IResourceLocation
[AsyncOperationHandle]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle-1
[AsyncOperationHandle.Task]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle-1.Task.html
[Completed callback]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle-1.Completed.html
[Coroutine]: xref:UnityEngine.Coroutine*
[HideFlags.DontUnloadUnusedAsset]: xref:UnityEngine.HideFlags.DontUnloadUnusedAsset
[LoadAssetAsync]: xref:UnityEngine.AddressableAssets.Addressables.LoadAssetAsync*
[LoadAssetsAsync]: xref:UnityEngine.AddressableAssets.Addressables.LoadAssetsAsync*
[LoadResourceLocationsAsync]: xref:UnityEngine.AddressableAssets.Addressables.LoadResourceLocationsAsync*
[LoadSceneMode.Single]: xref:UnityEngine.SceneManagement.LoadSceneMode.Single
[Memory Management]: xref:addressables-memory-management
[merge mode]: xref:UnityEngine.AddressableAssets.Addressables.MergeMode
[Object.DontDestroyOnLoad]: xref:UnityEngine.Object.DontDestroyOnLoad(UnityEngine.Object)
[OperationException]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle.OperationException
[Operations]: xref:addressables-async-operation-handling
[PrimaryKey]: xref:UnityEngine.ResourceManagement.ResourceLocations.IResourceLocation.PrimaryKey
[Releasing Addressable assets]: #releasing-addressable-assets
[ResourceManager.Acquire]: xref:UnityEngine.ResourceManagement.ResourceManager.Acquire(UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle)
[ResourceManager.CreateGenericGroupOperation]: xref:UnityEngine.ResourceManagement.ResourceManager.CreateGenericGroupOperation*
[Resources.UnloadUnusedAssets]: xref:UnityEngine.Resources.UnloadUnusedAssets
[Result]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle.Result
[SceneManager.LoadSceneAsync]: xref:UnityEngine.SceneManagement.SceneManager.LoadSceneAsync(System.String,UnityEngine.SceneManagement.LoadSceneMode)
[Status]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle.Status
[UnityEngine.Caching]: xref:UnityEngine.Caching
[ResourceManager.ExceptionHandler]: xref:UnityEngine.ResourceManagement.ResourceManager.ExceptionHandler
[Log Runtime Exceptions]: xref:addressables-asset-settings#diagnostics
[Console]: xref:Console
[Object.Instantiate]: xref:UnityEngine.Object.Instantiate*
[addresses]: xref:addressables-overview#asset-addresses
[labels]: xref:addressables-labels
[Completed]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle.Completed
[AsyncOperation.allowSceneActivation]: xref:UnityEngine.AsyncOperation.allowSceneActivation
[SceneInstance]: xref:UnityEngine.ResourceManagement.ResourceProviders.SceneInstance
[LoadSceneAsync]: xref:UnityEngine.SceneManagement.SceneManager.LoadSceneAsync(System.String,UnityEngine.SceneManagement.LoadSceneMode)
[UnloadAsset]: xref:UnityEngine.Resources.UnloadAsset(UnityEngine.Object)
[Addressables.InstantiateAsync]: xref:UnityEngine.AddressableAssets.Addressables.InstantiateAsync*
[Scene loading project]: https://github.com/Unity-Technologies/Addressables-Sample/tree/master/Basic/Scene%20Loading
[Addressables-Sample]: https://github.com/Unity-Technologies/Addressables-Sample
[Synchronous Addressables]: xref:synchronous-addressables
[Unloading Addressables]: xref:addressables-unloading

View file

@ -0,0 +1,127 @@
---
uid: addressables-loading-multiple-assets
---
# Loading multiple assets
Use the [LoadAssetsAsync] method to load more than one Addressable asset in a single operation. When using this function, you can specify a single key, such as a label, or a list of keys.
When you specify multiple keys, you can specify a [merge mode] to determine how the sets of assets matching each key are combined:
* __Union __: include assets that match any key
* __Intersection __: include assets that match every key
* __UseFirst__: include assets only from the first key that resolves to a valid location
[!code-cs[sample](../../Tests/Editor/DocExampleCode/LoadMultiple.cs#doc_Load)]
<!--
```csharp
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
public class LoadWithLabels : MonoBehaviour
{
// Label strings to load
public List<string> keys = new List<string>(){"characters", "animals"};
// Operation handle used to load and release assets
AsyncOperationHandle<IList<GameObject>> loadHandle;
// Load Addressables by Label
public IEnumerator Start() {
float x = 0, z = 0;
loadHandle = Addressables.LoadAssetsAsync<GameObject>(
keys,
addressable => {
//Gets called for every loaded asset
Instantiate<GameObject>(addressable,
new Vector3(x++ * 2.0f, 0, z * 2.0f),
Quaternion.identity,
transform);
if (x > 9)
{
x = 0;
z++;
}
}, Addressables.MergeMode.Union, // How to combine multiple labels
false); // Whether to fail and release if any asset fails to load
yield return loadHandle;
}
private void OnDestroy() {
Addressables.Release(loadHandle); // Release all the loaded assets associated with loadHandle
}
}
```
-->
You can specify how to handle loading errors with the `releaseDependenciesOnFailure` parameter. If true, then the operation fails if it encounters an error loading any single asset. The operation and any assets that did successfully load are released.
If false, then the operation loads any objects that it can and does not release the operation. In the case of failures, the operation still completes with a status of Failed. In addition, the list of assets returned has null values where the failed assets would otherwise appear.
Set `releaseDependenciesOnFailure` to true when loading a group of assets that must be loaded as a set in order to be used. For example, if you are loading the assets for a game level, it might make sense to fail the operation as a whole rather than load only some of the required assets.
[ActivateAsync]: xref:UnityEngine.ResourceManagement.ResourceProviders.SceneInstance.ActivateAsync*
[Addressables.ClearDependencyCacheAsync]: xref:UnityEngine.AddressableAssets.Addressables.ClearDependencyCacheAsync*
[Addressables.DownloadDependenciesAsync]: xref:UnityEngine.AddressableAssets.Addressables.DownloadDependenciesAsync*
[Addressables.GetDownloadSizeAsync]: xref:UnityEngine.AddressableAssets.Addressables.GetDownloadSizeAsync*
[Addressables.InstantiateAsync]: xref:UnityEngine.AddressableAssets.Addressables.InstantiateAsync*
[Addressables.LoadAssetAsync]: xref:UnityEngine.AddressableAssets.Addressables.LoadAssetAsync*
[Addressables.LoadSceneAsync]: xref:UnityEngine.AddressableAssets.Addressables.LoadSceneAsync*
[Addressables.ReleaseInstance]: xref:UnityEngine.AddressableAssets.Addressables.ReleaseInstance*
[Addressables]: xref:UnityEngine.AddressableAssets.Addressables
[Application.backgroundLoadingPriority]: xref:UnityEngine.Application.backgroundLoadingPriority
[AssetReference]: xref:UnityEngine.AddressableAssets.AssetReference
[AssetReferences]: xref:addressables-asset-references
[AsyncOperation.priority]: xref:UnityEngine.AsyncOperation.priority
[cache settings]: xref:UnityEngine.Cache
[Check Duplicate Bundle Dependencies]: AnalyzeTool.md#check-duplicate-bundle-dependencies
[GetDownloadStatus]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle.GetDownloadStatus*
[Instantiate]: xref:UnityEngine.Object.Instantiate*
[InstantiateAsync]: xref:UnityEngine.AddressableAssets.Addressables.InstantiateAsync*
[InstantiationParameters]: xref:UnityEngine.ResourceManagement.ResourceProviders.InstantiationParameters
[IResourceLocation]: xref:UnityEngine.ResourceManagement.ResourceLocations.IResourceLocation
[AsyncOperationHandle]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle-1
[AsyncOperationHandle.Task]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle-1.Task.html
[Completed callback]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle-1.Completed.html
[Coroutine]: xref:UnityEngine.Coroutine*
[HideFlags.DontUnloadUnusedAsset]: xref:UnityEngine.HideFlags.DontUnloadUnusedAsset
[LoadAssetAsync]: xref:UnityEngine.AddressableAssets.Addressables.LoadAssetAsync*
[LoadAssetsAsync]: xref:UnityEngine.AddressableAssets.Addressables.LoadAssetsAsync*
[LoadResourceLocationsAsync]: xref:UnityEngine.AddressableAssets.Addressables.LoadResourceLocationsAsync*
[LoadSceneMode.Single]: xref:UnityEngine.SceneManagement.LoadSceneMode.Single
[Memory Management]: xref:addressables-memory-management
[merge mode]: xref:UnityEngine.AddressableAssets.Addressables.MergeMode
[Object.DontDestroyOnLoad]: xref:UnityEngine.Object.DontDestroyOnLoad(UnityEngine.Object)
[OperationException]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle.OperationException
[Operations]: xref:addressables-async-operation-handling
[PrimaryKey]: xref:UnityEngine.ResourceManagement.ResourceLocations.IResourceLocation.PrimaryKey
[Releasing Addressable assets]: #releasing-addressable-assets
[ResourceManager.Acquire]: xref:UnityEngine.ResourceManagement.ResourceManager.Acquire(UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle)
[ResourceManager.CreateGenericGroupOperation]: xref:UnityEngine.ResourceManagement.ResourceManager.CreateGenericGroupOperation*
[Resources.UnloadUnusedAssets]: xref:UnityEngine.Resources.UnloadUnusedAssets
[Result]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle.Result
[SceneManager.LoadSceneAsync]: xref:UnityEngine.SceneManagement.SceneManager.LoadSceneAsync(System.String,UnityEngine.SceneManagement.LoadSceneMode)
[Status]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle.Status
[UnityEngine.Caching]: xref:UnityEngine.Caching
[ResourceManager.ExceptionHandler]: xref:UnityEngine.ResourceManagement.ResourceManager.ExceptionHandler
[Log Runtime Exceptions]: xref:addressables-asset-settings#diagnostics
[Console]: xref:Console
[Object.Instantiate]: xref:UnityEngine.Object.Instantiate*
[addresses]: xref:addressables-overview#asset-addresses
[labels]: xref:addressables-labels
[Completed]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle.Completed
[AsyncOperation.allowSceneActivation]: xref:UnityEngine.AsyncOperation.allowSceneActivation
[SceneInstance]: xref:UnityEngine.ResourceManagement.ResourceProviders.SceneInstance
[LoadSceneAsync]: xref:UnityEngine.SceneManagement.SceneManager.LoadSceneAsync(System.String,UnityEngine.SceneManagement.LoadSceneMode)
[UnloadAsset]: xref:UnityEngine.Resources.UnloadAsset(UnityEngine.Object)
[Addressables.InstantiateAsync]: xref:UnityEngine.AddressableAssets.Addressables.InstantiateAsync*
[Scene loading project]: https://github.com/Unity-Technologies/Addressables-Sample/tree/master/Basic/Scene%20Loading
[Addressables-Sample]: https://github.com/Unity-Technologies/Addressables-Sample
[Synchronous Addressables]: xref:synchronous-addressables
[Unloading Addressables]: xref:addressables-unloading

View file

@ -0,0 +1,117 @@
---
uid: addressables-loading-scenes
---
# Loading Scenes
Use the [Addressables.LoadSceneAsync] method to load an Addressable Scene asset by address or other Addressable key object.
> [!NOTE]
> [Addressables.LoadSceneAsync] uses the Unity Engine [SceneManager.LoadSceneAsync] method internally. API that affects the behaviour of [SceneManager.LoadSceneAsync] will most likely affect [Addressables.LoadSceneAsync] in the same way, for example [Application.backgroundLoadingPriority].
The remaining parameters of the method correspond to those used with the [SceneManager.LoadSceneAsync] method:
* __loadMode__: whether to add the loaded Scene into the current Scene or to unload and replace the current Scene.
* __loadSceneParameters__: includes loadMode in addition to localPhysicsMode, used when loading the Scene to specify whether a 2D and/or 3D physics Scene should be created
* __activateOnLoad__: whether to activate the scene as soon as it finishes loading or to wait until you call the SceneInstance object's [ActivateAsync] method. Corresponds to the [AsyncOperation.allowSceneActivation] option. Defaults to true.
* __priority__: the priority of the AsyncOperation used to load the Scene. Corresponds to the [AsyncOperation.priority] option. Defaults to 100.
> [!WARNING]
> Setting the `activateOnLoad` parameter to false blocks the AsyncOperation queue, including the loading of any other Addressable assets, until you activate the scene. To activate the scene, call the [ActivateAsync] method of the [SceneInstance] returned by [LoadSceneAsync]. See [AsyncOperation.allowSceneActivation] for additional information.
The following example loads a scene additively. The Component that loads the Scene, stores the operation handle and uses it to unload and release the Scene when the parent GameObject is destroyed.
[!code-cs[sample](../../Tests/Editor/DocExampleCode/LoadScene.cs#doc_Load)]
<!--
``` csharp
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.ResourceManagement.ResourceProviders;
using UnityEngine.SceneManagement;
public class LoadSceneByAddress : MonoBehaviour
{
public string key;
private AsyncOperationHandle<SceneInstance> loadHandle;
void Start()
{
loadHandle = Addressables.LoadSceneAsync(key, LoadSceneMode.Additive);
Destroy(this, 12); // Trigger unload to release Scene
}
void OnDestroy() {
Addressables.UnloadSceneAsync(loadHandle);
}
}
```
-->
See the [Scene loading project] in the [Addressables-Sample] repository for additional examples.
If you load a Scene with [LoadSceneMode.Single], the Unity runtime unloads the current Scene and calls [Resources.UnloadUnusedAssets]. See [Releasing Addressable assets] for more information.
> [!NOTE]
> In the Editor, you can always load scenes in the current project, even when they are packaged in a remote bundle that is not available and you set the Play Mode Script to __Use Existing Build__. The Editor loads the Scene using the asset database.
[ActivateAsync]: xref:UnityEngine.ResourceManagement.ResourceProviders.SceneInstance.ActivateAsync*
[Addressables.ClearDependencyCacheAsync]: xref:UnityEngine.AddressableAssets.Addressables.ClearDependencyCacheAsync*
[Addressables.DownloadDependenciesAsync]: xref:UnityEngine.AddressableAssets.Addressables.DownloadDependenciesAsync*
[Addressables.GetDownloadSizeAsync]: xref:UnityEngine.AddressableAssets.Addressables.GetDownloadSizeAsync*
[Addressables.InstantiateAsync]: xref:UnityEngine.AddressableAssets.Addressables.InstantiateAsync*
[Addressables.LoadAssetAsync]: xref:UnityEngine.AddressableAssets.Addressables.LoadAssetAsync*
[Addressables.LoadSceneAsync]: xref:UnityEngine.AddressableAssets.Addressables.LoadSceneAsync*
[Addressables.ReleaseInstance]: xref:UnityEngine.AddressableAssets.Addressables.ReleaseInstance*
[Addressables]: xref:UnityEngine.AddressableAssets.Addressables
[Application.backgroundLoadingPriority]: xref:UnityEngine.Application.backgroundLoadingPriority
[AssetReference]: xref:UnityEngine.AddressableAssets.AssetReference
[AssetReferences]: xref:addressables-asset-references
[AsyncOperation.priority]: xref:UnityEngine.AsyncOperation.priority
[cache settings]: xref:UnityEngine.Cache
[Check Duplicate Bundle Dependencies]: AnalyzeTool.md#check-duplicate-bundle-dependencies
[GetDownloadStatus]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle.GetDownloadStatus*
[Instantiate]: xref:UnityEngine.Object.Instantiate*
[InstantiateAsync]: xref:UnityEngine.AddressableAssets.Addressables.InstantiateAsync*
[InstantiationParameters]: xref:UnityEngine.ResourceManagement.ResourceProviders.InstantiationParameters
[IResourceLocation]: xref:UnityEngine.ResourceManagement.ResourceLocations.IResourceLocation
[AsyncOperationHandle]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle-1
[AsyncOperationHandle.Task]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle-1.Task.html
[Completed callback]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle-1.Completed.html
[Coroutine]: xref:UnityEngine.Coroutine*
[HideFlags.DontUnloadUnusedAsset]: xref:UnityEngine.HideFlags.DontUnloadUnusedAsset
[LoadAssetAsync]: xref:UnityEngine.AddressableAssets.Addressables.LoadAssetAsync*
[LoadAssetsAsync]: xref:UnityEngine.AddressableAssets.Addressables.LoadAssetsAsync*
[LoadResourceLocationsAsync]: xref:UnityEngine.AddressableAssets.Addressables.LoadResourceLocationsAsync*
[LoadSceneMode.Single]: xref:UnityEngine.SceneManagement.LoadSceneMode.Single
[Memory Management]: xref:addressables-memory-management
[merge mode]: xref:UnityEngine.AddressableAssets.Addressables.MergeMode
[Object.DontDestroyOnLoad]: xref:UnityEngine.Object.DontDestroyOnLoad(UnityEngine.Object)
[OperationException]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle.OperationException
[Operations]: xref:addressables-async-operation-handling
[PrimaryKey]: xref:UnityEngine.ResourceManagement.ResourceLocations.IResourceLocation.PrimaryKey
[Releasing Addressable assets]: xref:addressables-unloading
[ResourceManager.Acquire]: xref:UnityEngine.ResourceManagement.ResourceManager.Acquire(UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle)
[ResourceManager.CreateGenericGroupOperation]: xref:UnityEngine.ResourceManagement.ResourceManager.CreateGenericGroupOperation*
[Resources.UnloadUnusedAssets]: xref:UnityEngine.Resources.UnloadUnusedAssets
[Result]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle.Result
[SceneManager.LoadSceneAsync]: xref:UnityEngine.SceneManagement.SceneManager.LoadSceneAsync(System.String,UnityEngine.SceneManagement.LoadSceneMode)
[Status]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle.Status
[UnityEngine.Caching]: xref:UnityEngine.Caching
[ResourceManager.ExceptionHandler]: xref:UnityEngine.ResourceManagement.ResourceManager.ExceptionHandler
[Log Runtime Exceptions]: xref:addressables-asset-settings#diagnostics
[Console]: xref:Console
[Object.Instantiate]: xref:UnityEngine.Object.Instantiate*
[addresses]: xref:addressables-overview#asset-addresses
[labels]: xref:addressables-labels
[Completed]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle.Completed
[AsyncOperation.allowSceneActivation]: xref:UnityEngine.AsyncOperation.allowSceneActivation
[SceneInstance]: xref:UnityEngine.ResourceManagement.ResourceProviders.SceneInstance
[LoadSceneAsync]: xref:UnityEngine.SceneManagement.SceneManager.LoadSceneAsync(System.String,UnityEngine.SceneManagement.LoadSceneMode)
[UnloadAsset]: xref:UnityEngine.Resources.UnloadAsset(UnityEngine.Object)
[Addressables.InstantiateAsync]: xref:UnityEngine.AddressableAssets.Addressables.InstantiateAsync*
[Scene loading project]: https://github.com/Unity-Technologies/Addressables-Sample/tree/master/Basic/Scene%20Loading
[Addressables-Sample]: https://github.com/Unity-Technologies/Addressables-Sample
[Synchronous Addressables]: xref:synchronous-addressables
[Unloading Addressables]: xref:addressables-unloading

View file

@ -0,0 +1,104 @@
---
uid: addressables-loading-single-asset
---
# Loading a single asset
Use the [LoadAssetAsync] method to load a single Addressable asset, typically with an address as the key:
[!code-cs[sample](../../Tests/Editor/DocExampleCode/LoadSingle.cs#doc_Load)]
<!--
``` csharp
using System.Collections;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
public class LoadAddress : MonoBehaviour
{
public string key;
AsyncOperationHandle<GameObject> opHandle;
public IEnumerator Start()
{
opHandle = Addressables.LoadAssetAsync<GameObject>(key);
yield return opHandle;
if (opHandle.Status == AsyncOperationStatus.Succeeded) {
GameObject obj = opHandle.Result;
Instantiate(obj, transform);
GameObject.Destroy(gameObject, 12);
}
}
void OnDestroy()
{
Addressables.Release(opHandle);
}
}
```
-->
> [!NOTE]
> You can use a label or other type of key when you call [LoadAssetAsync], not just an address. However, if the key resolves to more than one asset, only the first asset found is loaded. For example, if you call this method with a label applied to several assets, Addressables returns whichever one of those assets that happens to be located first.
[ActivateAsync]: xref:UnityEngine.ResourceManagement.ResourceProviders.SceneInstance.ActivateAsync*
[Addressables.ClearDependencyCacheAsync]: xref:UnityEngine.AddressableAssets.Addressables.ClearDependencyCacheAsync*
[Addressables.DownloadDependenciesAsync]: xref:UnityEngine.AddressableAssets.Addressables.DownloadDependenciesAsync*
[Addressables.GetDownloadSizeAsync]: xref:UnityEngine.AddressableAssets.Addressables.GetDownloadSizeAsync*
[Addressables.InstantiateAsync]: xref:UnityEngine.AddressableAssets.Addressables.InstantiateAsync*
[Addressables.LoadAssetAsync]: xref:UnityEngine.AddressableAssets.Addressables.LoadAssetAsync*
[Addressables.LoadSceneAsync]: xref:UnityEngine.AddressableAssets.Addressables.LoadSceneAsync*
[Addressables.ReleaseInstance]: xref:UnityEngine.AddressableAssets.Addressables.ReleaseInstance*
[Addressables]: xref:UnityEngine.AddressableAssets.Addressables
[Application.backgroundLoadingPriority]: xref:UnityEngine.Application.backgroundLoadingPriority
[AssetReference]: xref:UnityEngine.AddressableAssets.AssetReference
[AssetReferences]: xref:addressables-asset-references
[AsyncOperation.priority]: xref:UnityEngine.AsyncOperation.priority
[cache settings]: xref:UnityEngine.Cache
[Check Duplicate Bundle Dependencies]: AnalyzeTool.md#check-duplicate-bundle-dependencies
[GetDownloadStatus]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle.GetDownloadStatus*
[Instantiate]: xref:UnityEngine.Object.Instantiate*
[InstantiateAsync]: xref:UnityEngine.AddressableAssets.Addressables.InstantiateAsync*
[InstantiationParameters]: xref:UnityEngine.ResourceManagement.ResourceProviders.InstantiationParameters
[IResourceLocation]: xref:UnityEngine.ResourceManagement.ResourceLocations.IResourceLocation
[AsyncOperationHandle]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle-1
[AsyncOperationHandle.Task]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle-1.Task.html
[Completed callback]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle-1.Completed.html
[Coroutine]: xref:UnityEngine.Coroutine*
[HideFlags.DontUnloadUnusedAsset]: xref:UnityEngine.HideFlags.DontUnloadUnusedAsset
[LoadAssetAsync]: xref:UnityEngine.AddressableAssets.Addressables.LoadAssetAsync*
[LoadAssetsAsync]: xref:UnityEngine.AddressableAssets.Addressables.LoadAssetsAsync*
[LoadResourceLocationsAsync]: xref:UnityEngine.AddressableAssets.Addressables.LoadResourceLocationsAsync*
[LoadSceneMode.Single]: xref:UnityEngine.SceneManagement.LoadSceneMode.Single
[Memory Management]: xref:addressables-memory-management
[merge mode]: xref:UnityEngine.AddressableAssets.Addressables.MergeMode
[Object.DontDestroyOnLoad]: xref:UnityEngine.Object.DontDestroyOnLoad(UnityEngine.Object)
[OperationException]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle.OperationException
[Operations]: xref:addressables-async-operation-handling
[PrimaryKey]: xref:UnityEngine.ResourceManagement.ResourceLocations.IResourceLocation.PrimaryKey
[Releasing Addressable assets]: #releasing-addressable-assets
[ResourceManager.Acquire]: xref:UnityEngine.ResourceManagement.ResourceManager.Acquire(UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle)
[ResourceManager.CreateGenericGroupOperation]: xref:UnityEngine.ResourceManagement.ResourceManager.CreateGenericGroupOperation*
[Resources.UnloadUnusedAssets]: xref:UnityEngine.Resources.UnloadUnusedAssets
[Result]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle.Result
[SceneManager.LoadSceneAsync]: xref:UnityEngine.SceneManagement.SceneManager.LoadSceneAsync(System.String,UnityEngine.SceneManagement.LoadSceneMode)
[Status]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle.Status
[UnityEngine.Caching]: xref:UnityEngine.Caching
[ResourceManager.ExceptionHandler]: xref:UnityEngine.ResourceManagement.ResourceManager.ExceptionHandler
[Log Runtime Exceptions]: xref:addressables-asset-settings#diagnostics
[Console]: xref:Console
[Object.Instantiate]: xref:UnityEngine.Object.Instantiate*
[addresses]: xref:addressables-overview#asset-addresses
[labels]: xref:addressables-labels
[Completed]: xref:UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle.Completed
[AsyncOperation.allowSceneActivation]: xref:UnityEngine.AsyncOperation.allowSceneActivation
[SceneInstance]: xref:UnityEngine.ResourceManagement.ResourceProviders.SceneInstance
[LoadSceneAsync]: xref:UnityEngine.SceneManagement.SceneManager.LoadSceneAsync(System.String,UnityEngine.SceneManagement.LoadSceneMode)
[UnloadAsset]: xref:UnityEngine.Resources.UnloadAsset(UnityEngine.Object)
[Addressables.InstantiateAsync]: xref:UnityEngine.AddressableAssets.Addressables.InstantiateAsync*
[Scene loading project]: https://github.com/Unity-Technologies/Addressables-Sample/tree/master/Basic/Scene%20Loading
[Addressables-Sample]: https://github.com/Unity-Technologies/Addressables-Sample
[Synchronous Addressables]: xref:synchronous-addressables
[Unloading Addressables]: xref:addressables-unloading

View file

@ -0,0 +1,117 @@
---
uid: addressables-memory-management
---
# Memory management
The Addressables system manages the memory used to load assets and bundles by keeping a reference count of every item it loads.
When an Addressable is loaded, the system increments the reference count; when the asset is released, the system decrements the reference count. When the reference count of an Addressable returns to zero, it is eligible to be unloaded. When you explicitly load an Addressable asset, you must also release the asset when you are done with it.
The basic rule of thumb to avoid "memory leaks" (assets that remain in memory after they are no longer needed) is to mirror every call to a load function with a call to a release function. You can release an asset with a reference to the asset instance itself or with the result handle returned by the original load operation.
Note, however, that released assets are not necessarily unloaded from memory immediately. The memory used by an asset is not freed until the AssetBundle it belongs to is also unloaded. (Released assets can also be unloaded by calling [Resources.UnloadUnusedAssets], but that tends to be a slow operation which can cause frame rate hitches.)
AssetBundles have their own reference count (the system treats them like Addressables with the assets they contain as dependencies). When you load an asset from a bundle, the bundle's reference count increases and when you release the asset, the bundle reference count decreases. When a bundle's reference count returns to zero, that means none of the assets it contains are still in use and the bundle and all the assets it contains are unloaded from memory.
Use the [Event Viewer] to monitor your runtime memory management. The viewer shows when assets and their dependencies are loaded and unloaded.
<a name="when-is-memory-cleared"></a>
## Understanding when memory is cleared
An asset no longer being referenced (indicated by the end of a blue section in the [Event Viewer]) does not necessarily mean that asset was unloaded. A common applicable scenario involves multiple assets in an AssetBundle. For example:
* You have three Assets (`tree`, `tank`, and `cow`) in an AssetBundle (`stuff`).
* When `tree` loads, the profiler displays a single ref-count for `tree`, and one for `stuff`.
* Later, when `tank` loads, the profiler displays a single ref-count for both `tree` and `tank`, and two ref-counts for the `stuff` AssetBundle.
* If you release `tree`, it's ref-count becomes zero, and the blue bar goes away.
In this example, the `tree` asset is not actually unloaded at this point. You can load an AssetBundle, or its partial contents, but you cannot partially unload an AssetBundle. No asset in stuff unloads until the AssetBundle itself is completely unloaded. The exception to this rule is the engine interface [Resources.UnloadUnusedAssets]. Executing this method in the above scenario causes `tree` to unload. Because the Addressables system cannot be aware of these events, the profiler graph only reflects the Addressables ref-counts (not exactly what memory holds). Note that if you choose to use [Resources.UnloadUnusedAssets], it is a very slow operation, and should only be called on a screen that won't show any hitches (such as a loading screen).
## Avoiding asset churn
Asset churn is a problem that can arise if you release an object that happens to be the last item in an AssetBundle and then immediately reload either that asset or another asset in the bundle.
For example, say you have two materials, `boat` and `plane` that share a texture, `cammo`, which has been pulled into its own AssetBundle. Level 1 uses `boat` and level 2 uses `plane`. As you exit level 1 you release `boat`, and immediately load `plane`. When you release `boat`, Addressables unloads texture `cammo`. Then, when you load `plane`, Addressables immediately reloads `cammo`.
You can use the [Event Viewer] to help detect asset churn by monitoring asset loading and unloading.
## AssetBundle memory overhead
When you load an AssetBundle, Unity allocates memory to store the bundle's internal data, which is in addition to the memory used for the assets it contains. The main types of internal data for a loaded AssetBundle include:
* Loading cache: Stores recently accessed pages of an AssetBundle file. Use [AssetBundle.memoryBudgetKB] to control its size.
* [TypeTrees]: Defines the serialized layout of your objects.
* [Table of contents]: Lists the assets in a bundle.
* [Preload table]: Lists the dependencies of each asset.
When you organize your Addressable groups and AssetBundles, you typically must make trade-offs between the size and the number of AssetBundles you create and load. On the one hand, fewer, larger bundles can minimize the total memory usage of your AssetBundles. On the other hand, using a larger number of small bundles can minimize the peak memory usage because you can unload assets and AssetBundles more easily.
While the size of an AssetBundle on disk is not the same as its size at runtime, you can use the disk size as an approximate guide to the memory overhead of the AssetBundles in a build. You can get bundle size and other information you can use to help analyze your AssetBundles from the [Build Layout Report].
The following sections discuss the internal data used by AssetBundles and how you can minimize the amount of memory they require, where possible.
### TypeTrees
A TypeTree describes the field layout of one of your data types.
Each serialized file in an AssetBundle contains a TypeTree for each object type within the file. The TypeTree information allows you to load objects that are deserialized slightly differently from the way they were serialized. TypeTree information is not shared between AssetBundles; each bundle has a complete set of TypeTrees for the objects it contains.
All the TypeTrees are loaded when the AssetBundle is loaded and held in memory for the lifetime of the AssetBundle. The memory overhead associated with TypeTrees is proportional to the number of unique types in the serialized file and the complexity of those types.
You can reduce the memory requirements of AssetBundle TypeTrees in the following ways:
* Keep assets of the same types together in the same bundles.
* Turn off TypeTrees -- turning off TypeTrees makes your AssetBundles smaller by excluding this information from a bundle. However, without TypeTree information, you may encounter serialization errors or undefined behavior when loading older bundles with a newer version of Unity or after making even small script changes in your project.
* Prefer simpler data types to reduce TypeTree complexity.
You can test the impact that TypeTrees have on the size of your AssetBundles by building them with and without TypeTrees disabled and comparing the sizes. Use [BuildAssetBundleOptions.DisableWriteTypeTree] to disable TypeTrees in your AssetBundles. Note that not all platforms support TypeTrees and some platforms require TypeTrees (and ignore this setting).
If you disable TypeTrees in a project, always rebuild local Addressable groups before building a new player. If you are distributing content remotely, only update content using the same version (including patch number) of Unity that you used to produce your current player and don't make even minor code changes. (When you are juggling multiple player versions, updates, and versions of Unity, you might not find the memory savings from disabling TypeTrees to be worth the trouble.)
### Table of contents
The table of contents is a map within the bundle that allows you to look up each explicitly included asset by name. It scales linearly with the number of assets and the length of the string names by which they are mapped.
The size of your table of contents data is based on the total number of assets. You can minimize the amount of memory dedicated to holding table of content data by minimizing the number of AssetBundles loaded at a given time.
### Preload table
The preload table is a list of all the other objects that an asset references. Unity uses the preload table to load these referenced objects when you load an asset from the AssetBundle.
For example, a Prefab has a preload entry for each of its components as well as any other assets it may reference (materials, textures, etc). Each preload entry is 64 bits and can reference objects in other AssetBundles.
When an asset references another asset that in turn references other assets, the preload table can become large because it contains the entries needed to load both assets. If two assets both reference a third asset, then the preload tables of both contain entries to load the third asset (whether or not the referenced asset is Addressable or in the same AssetBundle).
As an example, consider a situation in which you have two assets in an AssetBundle (PrefabA and PrefabB) and both of these prefabs reference a third prefab (PrefabC), which is large and contains several components and references to other assets. This AssetBundle contains two preload tables, one for PrefabA and one for PrefabB. Those tables contain entries for all the objects of their respective prefab, but also entries for all the objects in PrefabC and any objects referenced by PrefabC. Thus the information required to load PrefabC ends up duplicated in both PrefabA and PrefabB. This happens whether or not PrefabC is explicitly added to an AssetBundle.
Depending on how you organize your assets, the preload tables in AssetBundles could become quite large and contain many duplicate entries. This is especially true if you have several loadable assets that all reference a complex asset, such as PrefabC in the situation above. If you determine that the memory overhead from the preload table is a problem, you can structure your loadable assets so that they have fewer complex loading dependencies.
## Memory implications of loading AssetBundle dependencies
Loading an Addressable asset also loads all of the AssetBundles containing its dependencies. An AssetBundle dependency occurs when an asset in one bundle references an asset in another bundle. An example of this is a material referencing a texture. For more information see [Asset and AssetBundle dependencies].
Addressables calculates dependencies between bundles at the bundle level. If one asset references an object in another bundle, then the entire bundle has a dependency on that bundle. This means that even if you load an asset in the first bundle that has no dependencies of its own, the second AssetBundle is still loaded into memory.
For Example:
`BundleA` contains Addressable Assets `RootAsset1` and `RootAsset2`. `RootAsset2` references `DependencyAsset3`, which is contained in `BundleB`. Even though `RootAsset1` has no reference to `BundleB`, `BundleB` is still a dependency of `RootAsset1` because `RootAsset1` is in `BundleA`, which has a reference on `BundleB`.
> [!NOTE]
> Prior to Addressables 1.13.0, the dependency graph was not as thorough as it is now. In the example above, RootAsset1 would not have had a dependency on BundleB. This previous behavior resulted in references breaking when an AssetBundle being referenced by another AssetBundle was unloaded and reloaded. This fix may result in additional data remaining in memory if the dependency graph is complex enough.
To avoid loading more bundles than are required, you should strive to keep the dependencies between AssetBundles as simple as possible. There are several diagnostic tools included with Addressables that can be used to accomplish this:
* [Analyze Tool]
* [Build Layout Report]
[TypeTrees]: #typetrees
[Table of contents]: #table-of-contents
[Preload table]: #preload-table
[Build Layout Report]: xref:addressables-build-layout-report
[BuildAssetBundleOptions.DisableWriteTypeTree]: xref:UnityEditor.BuildAssetBundleOptions.DisableWriteTypeTree
[Event Viewer]: xref:addressables-event-viewer
[Resources.UnloadUnusedAssets]: xref:UnityEngine.Resources.UnloadUnusedAssets
[Asset and AssetBundle dependencies]: xref:addressables-asset-dependencies
[AssetBundle.memoryBudgetKB]: xref:UnityEngine.AssetBundle.memoryBudgetKB
[Analyze Tool]: xref:addressables-analyze-tool

View file

@ -0,0 +1,67 @@
---
uid: addressable-runtime
---
# Using Addressables at runtime
Once you have your Addressable assets organized into groups and built into AssetBundles, you must still load, instantiate, and, in the end release them at runtime.
Addressables uses a reference counting system to make sure that assets are only kept in memory while they are needed. See [Memory management] for more information about reference counting and how you can minimize the amount of memory used by assets at any given time.
Addressables provides several options and APIs for loading and instantiating Addressable assets. See [Loading Addressable assets] for information and examples, including:
* [Loading an single asset]
* [Loading multiple assets]
* [Loading an AssetReference]
* [Loading Scenes]
* [Loading assets by location]
* [Instantiating objects from Addressables]
* [Releasing Addressable assets]
* [Using Addressables in a Scene]
* [Downloading dependencies in advance]
Addressables uses asynchronous operations for most loading tasks. See [Operations] for information on how to handle operations in your code, including:
* [Releasing AsyncOperationHandle instances]
* [Coroutine- and IEnumerator-based operation handling]
* [Event-based operation handling]
* [Task-based operation handling]
* [Using operations synchronously]
* [Custom operations]
* [Using typed versus untyped operation handles]
* [Reporting operation progress]
See the following for information about other runtime topics:
* [Customizing initialization]
* [Loading additional catalogs]
* [Updating catalogs]
* [Modifying resource URLs at runtime]
* [Getting the address of an asset at runtime]
[Loading Addressable assets]: xref:addressables-api-load-asset-async
[Loading an single asset]: xref:addressables-loading-single-asset
[Loading multiple assets]: xref:addressables-loading-multiple-assets
[Loading an AssetReference]: xref:addressables-loading-asset-reference#loading-an-assetreference
[Loading assets by location]: xref:addressables-api-load-asset-async#loading-assets-by-location
[Loading Scenes]: xref:addressables-loading-scenes
[Instantiating objects from Addressables]: xref:addressables-instantiating#instantiate
[Releasing Addressable assets]: xref:addressables-unloading
[Using Addressables in a Scene]: xref:addressables-api-load-asset-async#using-addressables-in-a-scene
[Downloading dependencies in advance]: xref:addressables-api-download-dependencies-async
[Releasing AsyncOperationHandle instances]: xref:addressables-async-operation-handling#releasing-asyncoperationhandle-instances
[Coroutine- and IEnumerator-based operation handling]:xref:addressables-async-operation-handling#coroutine-operation-handling
[Event-based operation handling]: xref:addressables-async-operation-handling#event-based-operation-handling
[Task-based operation handling]: xref:addressables-async-operation-handling#task-based-operation-handling
[Using operations synchronously]: xref:addressables-async-operation-handling#using-operations-synchronously
[Custom operations]: xref:addressables-async-operation-handling#custom-operations
[Using typed versus untyped operation handles]: xref:addressables-async-operation-handling#using-typed-versus-typeless-operation-handles
[Reporting operation progress]: xref:addressables-async-operation-handling#reporting-operation-progress
[Operations]: xref:addressables-async-operation-handling
[Customizing initialization]: xref:addressables-api-initialize-async
[Loading additional catalogs]: xref:addressables-api-load-content-catalog-async#loading-additional-catalogs
[Updating catalogs]: xref:addressables-api-load-content-catalog-async#updating-catalogs
[Modifying resource URLs at runtime]: xref:addressables-api-transform-internal-id
[Getting the address of an asset at runtime]: xref:addressables-get-address
[Memory management]: xref:addressables-memory-management

View file

@ -0,0 +1,73 @@
---
uid: synchronous-addressables
---
## Synchronous Workflow
Synchronous Addressables APIs help to more closely mirror Unity asset loading workflows. `AsyncOperationHandles` now have a method called `WaitForCompletion()` that force the async operation to complete and return the `Result` of the operation.
## API
`TObject WaitForCompletion()`
## Result
The result of `WaitForCompletion` is the `Result` of the async operation it is called on. If the operation fails, this returns `default(TObject)`.
It is possible to get a `default(TObject)` for a result when the operation doesn't fail. Async operations that auto release their `AsyncOperationHandles` on completion are such cases. `Addressables.InitializeAsync()` and any API with a `autoReleaseHandle` parameter set to true will return `default(TObject)` even though the operations themselves succeeded.
## Performance
It is worth noting that calling `WaitForCompletion` may have performance implications on your runtime when compared to `Resources.Load` or `Instantiate` calls directly. If your `AssetBundle` is local or has been previously downloaded and cached, these performance hits are likely to be negligible. However, this may not be the case for your individual project setup.
All currently active Asset Load operations are completed when `WaitForCompletion` is called on any Asset Load operation, due to how Async operations are handled in the Engine. To avoid unexpected stalls, use `WaitForCompletion` when the current operation count is known, and the intention is for all active operations to complete synchronously.
When using `WaitForCompletion`, there are performance implications. When using 2021.2.0 or newer, these are minimal. Using an older version can result in delays that scale with the number of Engine Asset load calls that are loading when `WaitForCompletion` is called.
It is not recommended that you call `WaitForCompletion` on an operation that is going to fetch and download a remote `AssetBundle`. Though, it is possible if that fits your specific situation.
## Code Sample
```
void Start()
{
//Basic use case of forcing a synchronous load of a GameObject
var op = Addressables.LoadAssetAsync<GameObject>("myGameObjectKey");
GameObject go = op.WaitForCompletion();
//Do work...
Addressables.Release(op);
}
```
### Scenes
Due to engine limitations scenes cannot be completed synchronously. Calling WaitForCompletion on an operation returned from [Addressables.LoadSceneAsync] will not completely load the scene, even if activateOnLoad is set to true. It will wait for dependencies and assets to complete but the scene activation must be done asynchronously. This can be done using the sceneHandle, or by the [AsyncOperation] from ActivateAsync on the SceneInstance as shown below.
```c#
IEnumerator LoadScene(string myScene)
{
var sceneHandle = Addressables.LoadSceneAsync(myScene, LoadSceneMode.Additive);
SceneInstance sceneInstance = sceneHandle.WaitForCompletion();
yield return sceneInstance.ActivateAsync();
//Do work... the scene is now complete and integrated
}
```
> [!NOTE]
> Unloading a scene cannot be completed synchronously. Calling WaitForCompleted on a scene unload will not unload the scene or any assets, and a warning will be logged to the console.
>[!NOTE]
>Due to limitations with Scene integration on the main thread through the `SceneManager` API, it is possible to lock the Editor or Player when calling `WaitForCompletion` in association with scene loading. The issue primarily surfaces when loading two scenes in succession, with the second scene load request having `WaitForCompletion` called from its `AsyncOperationHandle`. Since scene loading takes extra frames to fully integrate on the main thread, and `WaitForCompletion` locks the main thread, you could hit a situation where Addressables has been informed by the `SceneManager` that the first scene is fully loaded, even though it hasn't completed finished all the required operations. At this point, the scene is fully loaded, but the `SceneManager` attempts to call `UnloadUnusedAssets`, on the main thread, if the scene was loaded in `Single` mode. Then, the second scene load request locks the main thread with `WaitForCompletion`, but cannot begin loading because `SceneManager` requires the `UnloadUnusedAssets` to complete before the next scene can begin loading.
>In order to avoid this deadlock, it is advised that you either load successive scenes asynchronously, or ensure a sufficient delay is added between scene load requests.
### Synchronous Addressables with Custom Operations
Addressables supports custom `AsyncOperations` which support unique implementations of `InvokeWaitForCompletion`. This method can be overridden to implement custom synchronous operations.
Custom operations work with `ChainOperations` and `GroupsOperations`. If you require chained operations to be completed synchronously, ensure that your custom operations implement `InvokeWaitForCompletion` and create a `ChainOperation` using your custom operations. Similarly, `GroupOperations` are well suited to ensure a collection of `AsyncOperations`, including custom operations, complete together. Both `ChainOperation` and `GroupOperation` have their own implementations of `InvokeWaitForCompletion` that relies on the `InvokeWaitForCompletion` implementations of the operations they depend on.
### WebGL
WebGL does not support `WaitForCompletion`. On WebGL, all files are loaded using a web request. On other platforms, a web request gets started on a background thread and the main thread spins in a tight loop while waiting for the web request to finish. This is how Addressables does it for `WaitForCompletion` when a web request is used.
Since WebGL is single-threaded, the tight loop blocks the web request and the operation is never allowed to finish. If a web request finishes the same frame it was created, then `WaitForCompletion` wouldn't have any issue. However, we cannot guarantee this to be the case, and likely it isn't the case for most instances.
[AsyncOperation.allowSceneActivation]: xref:UnityEngine.AsyncOperation.allowSceneActivation
[AsyncOperation]: xref:UnityEngine.AsyncOperation
[Addressables.LoadSceneAsync]: xref:UnityEngine.AddressableAssets.Addressables.LoadSceneAsync*
[Addressables.UnloadSceneAsync]: xref:UnityEngine.AddressableAssets.Addressables.UnloadSceneAsync

View file

@ -0,0 +1,126 @@
---
uid: addressables-api-transform-internal-id
---
<a name="modify-resoure-urls"></a>
# Transforming resource URLs
Addressables provides the following ways to modify the URLs it uses to load assets at runtime:
* Static properties in a Profile variable
* Implementing an ID transform function
* Implementing a WebRequestOverride method
## Static Profile variables
You can use a static property when defining the [RemoteLoadPath Profile variable] to specify all or part of the URL from which your application loads remote content, including catalogs, catalog hash files, and AssetBundles. See [Profile variable syntax] for information about specifying a property name in a Profile variable. The value of your static property must be set before Addressables initializes. Changing the value after initialization has no effect.
## ID transform function
You can assign a function to the [Addressables.ResourceManager] object's [InternalIdTransformFunc] property to individually change the URLs from which Addressables loads assets. You must assign the function before the relevant operation starts, otherwise the default URL is used.
Using TransformInternalId grants a fair amount of flexibility, especially in regards to remote hosting. Given a single IResourceLocation, you can transform the ID to point towards a server specified at runtime. This is particularly useful if your server IP address changes or if you use different URLS to provide different variants of your application assets.
The ResourceManager calls your TransformInternalId function when it looks up an asset, passing the [IResourceLocation] instance for the asset to your function. You can change the [InternalId] property of this IResourceLocation and return the modified object to the ResourceManager.
The following example illustrates how you could append a query string to all URLs for AssetBundles:
[!code-cs[sample](../../Tests/Editor/DocExampleCode/IDTransformer.cs#doc_Transformer)]
<!--
```csharp
//Implement a method to transform the internal ids of locations
string MyCustomTransform(IResourceLocation location)
{
if (location.ResourceType == typeof(IAssetBundleResource) && location.InternalId.StartsWith("http"))
return location.InternalId + "?customQueryTag=customQueryValue";
return location.InternalId;
}
//Override the Addressables transform method with your custom method. This can be set to null to revert to default behavior.
[RuntimeInitializeOnLoadMethod]
static void SetInternalIdTransform()
{
Addressables.InternalIdTransformFunc = MyCustomTransform;
}
```
-->
## WebRequest override
You can assign a function to the [Addressables] object's [WebRequestOverride] property to individually modify the [UnityWebRequest] from which is used to download files, such as an AssetBundle or catalog json file. You must assign the function before the relevant operation starts, otherwise the default UnityWebRequest is used.
The ResourceManager calls your [WebRequestOverride] function before [UnityWebRequest.SendWebRequest] is called. Passing the UnityWebRequest for the download to your function.
The following example illustrates how you could append a query string to all URLs for AssetBundles and catalogs:
[!code-cs[sample](../../Tests/Editor/DocExampleCode/WebRequestOverride.cs#doc_TransformerWebRequest)]
<!--
```csharp
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.AddressableAssets;
public class WebRequestOverride : MonoBehaviour
{
//Register to override WebRequests Addressables creates
//The UnityWebRequests will default to the standard behavior
private void Start()
{
Addressables.WebRequestOverride = EditWebRequestURL;
}
//Override the url of the WebRequest
private void EditWebRequestURL(UnityWebRequest request)
{
if (request.url.EndsWith(".bundle"))
request.url = request.url + "?customQueryTag=customQueryValue";
else if (request.url.EndsWith(".json") || request.url.EndsWith(".hash"))
request.url = request.url + "?customQueryTag=customQueryValue";
}
}
```
-->
[Addressables]: xref:UnityEngine.AddressableAssets.Addressables
[WebRequestOverride]: xref:UnityEngine.AddressableAssets.Addressables.WebRequestOverride
[UnityWebRequest]: xref:UnityEngine.Networking.UnityWebRequest
[UnityWebRequest.SendWebRequest]: xref:UnityEngine.Networking.UnityWebRequest.SendWebRequest
[Addressables.CheckForCatalogUpdates]: xref:UnityEngine.AddressableAssets.Addressables.CheckForCatalogUpdates*
[Addressables.InitializeAsync]: xref:UnityEngine.AddressableAssets.Addressables.InitializeAsync*
[Addressables.LoadContentCatalogAsync]: xref:UnityEngine.AddressableAssets.Addressables.LoadContentCatalogAsync*
[Addressables.ResourceManager]: xref:UnityEngine.AddressableAssets.Addressables.ResourceManager
[Addressables.UpdateCatalogs]: xref:UnityEngine.AddressableAssets.Addressables.UpdateCatalogs*
[Build Remote Catalog]: xref:addressables-asset-settings#catalog
[Cache]: xref:UnityEngine.Cache
[CacheInitializationSettings]: xref:UnityEditor.AddressableAssets.Settings.CacheInitializationSettings
[Caching]: xref:UnityEngine.Caching
[Catalog Download Timeout]: xref:addressables-asset-settings#downloads
[Content update builds]: xref:addressables-content-update-builds
[Custom certificate handler]: xref:addressables-asset-settings#downloads
[Custom URL transform function]: #id-transform-function
[Customizing initialization]: #customizing-initialization
[Only update catalogs manually]: xref:addressables-asset-settings#catalog
[Getting the address of an asset at runtime]: #getting-the-address-of-an-asset-at-runtime
[initialization object list]: xref:addressables-asset-settings#initialization-object-list
[initialization object]: xref:addressables-asset-settings#initialization-object-list
[InternalId]: xref:UnityEngine.ResourceManagement.ResourceLocations.IResourceLocation.InternalId
[IObjectInitializationDataProvider]: xref:UnityEngine.ResourceManagement.Util.IObjectInitializationDataProvider
[IResourceLocation]: xref:UnityEngine.ResourceManagement.ResourceLocations.IResourceLocation
[LoadContentCatalogAsync]: xref:UnityEngine.AddressableAssets.Addressables.LoadContentCatalogAsync*
[Loading additional catalogs]: #loading-additional-catalogs
[Loading Assets by Location]: xref:addressables-loading-assets#loading-assets-by-location
[Modifying resource URLs at runtime]: #modifying-resource-urls-at-runtime
[ObjectInitializationData]: xref:UnityEngine.ResourceManagement.Util.ObjectInitializationData
[PrimaryKey]: xref:UnityEngine.ResourceManagement.ResourceLocations.IResourceLocation.PrimaryKey
[Profile variable syntax]: xref:addressables-profile-variables#profile-variable-syntax
[Profile variables]: xref:addressables-profile-variables#profile-variable-syntax
[RemoteLoadPath Profile variable]: xref:addressables-profiles
[ResourceLocators]: xref:UnityEngine.AddressableAssets.ResourceLocators
[ResourceManager exception handler]: xref:UnityEngine.ResourceManagement.ResourceManager.ExceptionHandler
[ResourceManager]: xref:UnityEngine.ResourceManagement.ResourceManager
[InternalIdTransformFunc]: xref:UnityEngine.ResourceManagement.ResourceManager.InternalIdTransformFunc
[Unique Bundle Ids]: xref:addressables-content-update-builds#unique-bundle-ids-setting
[Updating catalogs]: #updating-catalogs

View file

@ -0,0 +1,23 @@
---
uid: addressables-unloading
---
# Unloading Addressable assets
The Addressables system uses reference counting to determine whether an asset is in use - as a result, you must release every asset that you load or instantiate when you're done with it. See [Memory Management] for more information.
When you unload a Scene, the AssetBundle it belongs to is unloaded. This unloads assets associated with the Scene, including any GameObjects moved from the original Scene to a different Scene.
Unity automatically calls `UnloadUnusedAssets` when it loads a Scene using the [LoadSceneMode.Single] mode. To prevent the Scene and its assets from being unloaded, maintain a reference to the scene load operation handle until the Scene should be unloaded manually. You can do this by using [ResourceManager.Acquire] on the load operation handle. Conventional methods of preserving the assets such as [Object.DontDestroyOnLoad] or [HideFlags.DontUnloadUnusedAsset] will not work.
Individual Addressables and their operation handles that you loaded separately from the Scene are not released. You must call [Resources.UnloadUnusedAssets] or [UnloadAsset] to free these assets. (The exception to this is that any Addressable assets that you instantiated using [Addressables.InstantiateAsync] with `trackHandle` set to true, the default, are automatically released.)
[Memory Management]: xref:addressables-memory-management
[LoadSceneMode.Single]: xref:UnityEngine.SceneManagement.LoadSceneMode.Single
[ResourceManager.Acquire]: xref:UnityEngine.ResourceManagement.ResourceManager.Acquire(UnityEngine.ResourceManagement.AsyncOperations.AsyncOperationHandle)
[Object.DontDestroyOnLoad]: xref:UnityEngine.Object.DontDestroyOnLoad(UnityEngine.Object)
[HideFlags.DontUnloadUnusedAsset]: xref:UnityEngine.HideFlags.DontUnloadUnusedAsset
[Resources.UnloadUnusedAssets]: xref:UnityEngine.Resources.UnloadUnusedAssets
[UnloadAsset]: xref:UnityEngine.Resources.UnloadAsset(UnityEngine.Object)
[Addressables.InstantiateAsync]: xref:UnityEngine.AddressableAssets.Addressables.InstantiateAsync*