Best Practices

Spatial performs very little validation on whether you are using Addressables correctly, so it is your responsibility to know how to use it properly. Failing to do so can hurt performance significantly.

Referencing Addressable Assets

Use the AssetReference type instead of GameObject when referencing an Addressable asset in your scripts. The AssetReference field will store the asset GUID as the "address" associated with the asset, instead of a direct reference to the asset itself, which will prevent it from accidentally being included in other asset bundles. As an added bonus, dragging a non-Addressable asset into the inspector field will automatically mark it as Addressable and add it to the default asset group.

// Referencing an Addressable asset in this field will likely end up increasing the download size, especially
// if it's loaded as an Addressable in some places and referenced as a GameObject in other places.
public GameObject notAddressableAsset;

// Assign Addressables to these fields instead!
public AssetReference addressableAsset;
public AssetReferenceGameObject addressableGameObject;
public AssetReferenceTexture2D addressableTexture;
public AssetReferenceT<AudioClip> addressableAudio;
// Referencing an Addressable asset in this field will likely end up increasing the download size, especially
// if it's loaded as an Addressable in some places and referenced as a GameObject in other places.
public GameObject notAddressableAsset;

// Assign Addressables to these fields instead!
public AssetReference addressableAsset;
public AssetReferenceGameObject addressableGameObject;
public AssetReferenceTexture2D addressableTexture;
public AssetReferenceT<AudioClip> addressableAudio;

Release Handles to Avoid Memory Leaks

All operation handles returned from Addressables API should be released when you've finished using it. Not doing so can cause your game to leak memory and potentially crash. You can call Addressables.Release(handle) to release any operation handle. If it's an AssetReference, then reference.ReleaseAsset() or reference.ReleaseInstance(gameObject) will also work.

// These can/should be added to a List<AsyncOperationHandle> to keep track of all of the Addressable handles
// managed by the script.
AsyncOperationHandle<GameObject> prefabInstanceHandle = Addressables.InstantiateAsync<GameObject>("big_prefab");
AsyncOperationHandle<Texture2D> textureHandle = Addressables.LoadAssetAsync<Texture2D>("some_texture");

// When the texture becomes unused, release the handle so it can be unloaded from memory if the
// reference count reaches 0. If it needs to be loaded again, it will be fetched from the disk cache.
Addressables.Release(textureHandle);

// Note that we're using ReleaseInstance() since it was instantiated.
// This will destroy the instance and decrement the reference count by 1.
Addressables.ReleaseInstance(prefabInstanceHandle);
// These can/should be added to a List<AsyncOperationHandle> to keep track of all of the Addressable handles
// managed by the script.
AsyncOperationHandle<GameObject> prefabInstanceHandle = Addressables.InstantiateAsync<GameObject>("big_prefab");
AsyncOperationHandle<Texture2D> textureHandle = Addressables.LoadAssetAsync<Texture2D>("some_texture");

// When the texture becomes unused, release the handle so it can be unloaded from memory if the
// reference count reaches 0. If it needs to be loaded again, it will be fetched from the disk cache.
Addressables.Release(textureHandle);

// Note that we're using ReleaseInstance() since it was instantiated.
// This will destroy the instance and decrement the reference count by 1.
Addressables.ReleaseInstance(prefabInstanceHandle);

Choose the Optimal Bundle Packing Mode

Not all assets have to be loaded the same way. You can configure how the assets are packed into bundles to fit the use case of an asset group. This setting can be changed through the Bundle Mode property in the Asset Group config asset.

Bundle Packing Method

MethodDescription
Pack TogetherCreates a single asset bundle that includes all assets in the asset group. Select this option if all asset entries in the group are dependent on each other, or if all assets will be downloaded together.
Pack SeparatelyCreates an asset bundle per asset entry in the group. The total download may be larger in some cases due to some shared dependencies being included in multiple bundles.
Pack Together By LabelCreates an asset bundle per label. Multiple assets can be assigned to a single label (e.g. rocket launcher and rocket), so this can be used to download similar assets in a single bundle whenever one of the assets gets loaded. You can use Addressables.LoadAssetsAsync("label_name") to load all assets associated with the label at once.

You can learn more about packing methods in Unity's official documentation