Quickstart Guide

Tutorial

Setting up Addressables in your Spatial Creator Toolkit project is as simple as setting up any other Unity project! If you have already used Addressables before, then you are likely familiar with most of these setup steps.

Tip

You can also find a separate template project with more in-depth logic here.

Step 1: Initialize Addressables

Open up the Spatial Portal window in Unity, navigate to the Utilities tab, then press the Initialize for Project button under the Addressables section.

Initialization Button

You should now see the AddressableAssetsData folder hierarchy generated from the initialization. This directory and its subdirectories should not be renamed or moved to ensure compatibility.

Addressables Folder Hierarchy

Without the presence of the AddressableAssetsData or the AssetGroups subdirectory, Addressables will be disabled. More details about the Addressables build process can be found in the Build Process page.

Step 2: Creating a Physics Cube for Testing

Create a new Cube in the scene and drag it into a folder of your choice in the Project view to convert the game object to a prefab. Add a Rigidbody component to the prefab asset.

Important

Be sure to delete the prefab instance from the scene to ensure it's not included in your main scene bundle. No other asset in the project should be referencing the prefab at this point.

Simple Cube Prefab

Step 3: Marking the Prefab as Addressable

Right now, the Cube prefab is not recognized by the Addressables system, so let's fix that!

Select the prefab asset and tick the checkbox near the top of the Inspector view that is labelled Addressable. This will automatically generate an Addressable name and add it to the default asset group. The Addressable name can be changed manually through the input field to anything you desire, but typically the chosen name shouldn't conflict with other Addressable assets to avoid confusion.

Click the Select button next to the input field, which will open the Asset Groups window (also accessible through the Window > Asset Management > Addressables > Groups menu item). You should see the Cube prefab under the default asset group.

Tip

You can also drag the prefab asset from the Project view into this window to add it to the desired group.

Asset Groups Window

If you wish, you can continue adding assets. Additional asset groups can also be created to separate different asset types or use different build settings, such as the bundle packing mode, that is optimal for the group's use case.

Step 4: Loading the Cube via C#

Now that the Cube prefab is Addressable, you can begin referencing it throughout your C# scripts. Let's create a simple, interactable spawner script that instantiates the Cube and throws it in a random upward direction.

  1. Create or assign a C# assembly in your Space config.

  2. Add Unity.Addressables and Unity.ResourceManager to your C# assembly's Assembly Definition References list, as shown below, and click Apply. Assembly Definition GUI

  3. Create a new script next to your C# assembly named AddressableSpawner.cs and replace its contents with the code below.

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.AddressableAssets;
    using UnityEngine.ResourceManagement.AsyncOperations;

    public class AddressableSpawner : MonoBehaviour
    {
    // IMPORTANT: Don't use the standard GameObject type to reference Addressables.
    // Always use AssetReference and its derived classes.
    [SerializeField] private AssetReferenceGameObject _cubeAddressable;

    private List<AsyncOperationHandle> _handles = new();

    private void OnDestroy()
    {
    // Release all cube instance handles managed by this spawner, which will prevent
    // the cube from leaking in memory.
    foreach (AsyncOperationHandle handle in _handles)
    Addressables.Release(handle); // Addressables.Release already checks for handle validity
    _handles.Clear();
    }

    // Invoke this through some event
    public void DoSpawnCube()
    {
    if (_cubeAddressable == null)
    return;
    StartCoroutine(SpawnCube());
    }

    private IEnumerator SpawnCube()
    {
    // Downloads (if not already cached) and spawns the cube.
    AsyncOperationHandle<GameObject> handle = _cubeAddressable.InstantiateAsync(transform.position, transform.rotation);
    // Store the handle reference in a list so that the asset can be cleaned up when the spawner is destroyed.
    _handles.Add(handle);

    // Wait for async operation to complete.
    yield return handle;

    if (handle.Status != AsyncOperationStatus.Succeeded)
    {
    // If it failed to load, abort and log an error to the console.
    Debug.LogError("Failed to load cube addressable!");
    yield break;
    }

    // Add some random upwards force to apply to the cube instance.
    GameObject cubeInstance = handle.Result;
    Rigidbody rb = cubeInstance.GetComponent<Rigidbody>();
    Vector3 force = new Vector3(Random.Range(-0.2f, 0.2f), 1f, Random.Range(-0.2f, 0.2f));
    rb.AddForce(force.normalized * 10f, ForceMode.Impulse);
    // Make the cube spin too, just for fun.
    rb.AddTorque(Random.onUnitSphere * 2f, ForceMode.VelocityChange);
    }
    }
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.AddressableAssets;
    using UnityEngine.ResourceManagement.AsyncOperations;

    public class AddressableSpawner : MonoBehaviour
    {
    // IMPORTANT: Don't use the standard GameObject type to reference Addressables.
    // Always use AssetReference and its derived classes.
    [SerializeField] private AssetReferenceGameObject _cubeAddressable;

    private List<AsyncOperationHandle> _handles = new();

    private void OnDestroy()
    {
    // Release all cube instance handles managed by this spawner, which will prevent
    // the cube from leaking in memory.
    foreach (AsyncOperationHandle handle in _handles)
    Addressables.Release(handle); // Addressables.Release already checks for handle validity
    _handles.Clear();
    }

    // Invoke this through some event
    public void DoSpawnCube()
    {
    if (_cubeAddressable == null)
    return;
    StartCoroutine(SpawnCube());
    }

    private IEnumerator SpawnCube()
    {
    // Downloads (if not already cached) and spawns the cube.
    AsyncOperationHandle<GameObject> handle = _cubeAddressable.InstantiateAsync(transform.position, transform.rotation);
    // Store the handle reference in a list so that the asset can be cleaned up when the spawner is destroyed.
    _handles.Add(handle);

    // Wait for async operation to complete.
    yield return handle;

    if (handle.Status != AsyncOperationStatus.Succeeded)
    {
    // If it failed to load, abort and log an error to the console.
    Debug.LogError("Failed to load cube addressable!");
    yield break;
    }

    // Add some random upwards force to apply to the cube instance.
    GameObject cubeInstance = handle.Result;
    Rigidbody rb = cubeInstance.GetComponent<Rigidbody>();
    Vector3 force = new Vector3(Random.Range(-0.2f, 0.2f), 1f, Random.Range(-0.2f, 0.2f));
    rb.AddForce(force.normalized * 10f, ForceMode.Impulse);
    // Make the cube spin too, just for fun.
    rb.AddTorque(Random.onUnitSphere * 2f, ForceMode.VelocityChange);
    }
    }
  4. In your scene, create an empty game object that will serve as the interactable spawner, then add the AddressableSpawner script to the object and assign the Cube Addressable prefab in the Inspector view.

    Add the Spatial Interactable component to the spawner. Then, create a new Unity Event entry under On Interact Event, assign the target object to the spawner itself, and select AddressableSpawner.DoSpawnCube() as the invocation target. Feel free to customize the other fields in the Spatial Interactable component to your liking.

    In the end, this is what it should look like: Interactable Unity Event

    Don't forget to save your scene.

Step 5: Testing in the Sandbox

The spawner should be all set up, so let's see it in action! Click on the Test Active Scene button to test out these changes. You should see cubes spawning and flying up when you interact with the spawner. When the cube spawns in for the first time, there will be a brief delay as the asset bundle downloads.

Cubes Flying Up

That's it! The cube should not be included in the main asset bundle, and it was only downloaded when necessary, which saved some load time and memory. The performance improvements will be more noticeable as you convert more assets to Addressables.

What's Next