Receber por email
← Voltar para o catálogo

addressables

Addressables asset loading — LoadAssetAsync, handle lifecycle, labels, remote catalogs, memory management. Use for asset loading and memory optimization.

21estrelas
Atualizado há 6 meses

Ver no GitHub ↗ Licença: MIT

Como adicionar

/plugin marketplace add XeldarAlz/everything-claude-unity

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Para o autor da skill

Cole no README do seu repo

Mostra que sua skill está catalogada na Skillteca, gera backlink e tráfego rastreável.

[![Skillteca](https://www.skillteca.com.br/api/badge/addressables/svg)](https://www.skillteca.com.br/skills/addressables)
#ai

Skills relacionadas

Ver todas de Desenvolvimento →

Alerta por categoria

Receba novas skills de Desenvolvimento toda segunda

1 email curto, só com as skills novas de Desenvolvimento. 4 minutos de leitura, sem spam, cancela com 1 clique.

Você confirma o email no primeiro envio. Sem spam. Cancela com 1 clique.

Ler descrição completa

Unity Addressables

Setup

  1. Install via Package Manager: com.unity.addressables
  2. Mark assets as Addressable in the Inspector checkbox
  3. Organize into Groups (local, remote, by scene, by feature)
  4. Assign Labels for batch loading (e.g., "level1", "enemies", "ui")

Group Organization Strategy

Groups:
  Local_Static       -- Core assets, always available (shaders, essential UI)
  Local_Dynamic      -- Assets that change between builds
  Remote_Levels      -- Level-specific assets, downloaded on demand
  Remote_Characters  -- Character models/animations

Loading Assets

Basic Asset Loading

using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;

public class AddressableLoader : MonoBehaviour
{
    [SerializeField] private AssetReference prefabReference;

    private AsyncOperationHandle<GameObject> _loadHandle;
    private GameObject _instance;

    public async void LoadAndInstantiate()
    {
        _loadHandle = Addressables.LoadAssetAsync<GameObject>(prefabReference);
        await _loadHandle.Task;

        if (_loadHandle.Status == AsyncOperationStatus.Succeeded)
        {
            _instance = Instantiate(_loadHandle.Result);
        }
        else
        {
            Debug.LogError($"Failed to load addressable: {_loadHandle.OperationException}");
        }
    }

    // CRITICAL: Always release handles to prevent memory leaks
    private void OnDestroy()
    {
        if (_loadHandle.IsValid())
        {
            Addressables.Release(_loadHandle);
        }

        if (_instance != null)
        {
            Destroy(_instance);
        }
    }
}

InstantiateAsync (Load + Instantiate in One Call)

public class AddressableInstantiator : MonoBehaviour
{
    [SerializeField] private AssetReference prefabReference;
    private AsyncOperationHandle<GameObject> _instanceHandle;

    public async void SpawnObject(Vector3 position, Quaternion rotation)
    {
        _instanceHandle = Addressables.InstantiateAsync(prefabReference, position, rotation);
        await _instanceHandle.Task;

        if (_instanceHandle.Status != AsyncOperationStatus.Succeeded)
        {
            Debug.LogError("Failed to instantiate addressable");
        }
    }

    private void OnDestroy()
    {
        // ReleaseInstance destroys the object AND releases the handle
        if (_instanceHandle.IsValid())
        {
            Addressables.ReleaseInstance(_instanceHandle);
        }
    }
}

Handle Lifecycle (CRITICAL)

Every LoadAssetAsync or InstantiateAsync call returns a handle that MUST be released.

Rules

  1. Every load must have a matching release. No exceptions.
  2. Track all handles. Store them in fields or a list.
  3. Release on destroy. Use OnDestroy or a dedicated cleanup method.
  4. Check IsValid() before releasing. Prevents double-release errors.

Handle Tracking Pattern

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

public class AddressableManager : MonoBehaviour
{
    private readonly List<AsyncOperationHandle> _handles = new();

    public AsyncOperationHandle<T> LoadAsset<T>(object key)
    {
        var handle = Addressables.LoadAssetAsync<T>(key);
        _handles.Add(handle);
        return handle;
    }

    public AsyncOperationHandle<GameObject> InstantiateAsset(AssetReference reference,
        Vector3 position = default, Quaternion rotation = default)
    {
        var handle = Addressables.InstantiateAsync(reference, position, rotation);
        _handles.Add(handle);
        return handle;
    }

    public void ReleaseAll()
    {
        foreach (var handle in _handles)
        {
            if (handle.IsValid())
            {
                Addressables.Release(handle);
            }
        }
        _handles.Clear();
    }

    private void OnDestroy()
    {
        ReleaseAll();
    }
}

Label-Based Loading

Load multiple assets sharing a label in a single call.

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

public class LevelAssetLoader : MonoBehaviour
{
    private AsyncOperationHandle<IList<GameObject>> _levelAssetsHandle;

    public async void LoadLevelAssets(string levelLabel)
    {
        _levelAssetsHandle = Addressables.LoadAssetsAsync<GameObject>(
            levelLabel,
            prefab =>
            {
                // Called for EACH asset as it loads
                Debug.Log($"Loaded: {prefab.name}");
            });

        await _levelAssetsHandle.Task;

        if (_levelAssetsHandle.Status == AsyncOperationStatus.Succeeded)
        {
            Debug.Log($"All {_levelAssetsHandle.Result.Count} assets loaded for {levelLabel}");
        }
    }

    public void UnloadLevelAssets()
    {
        if (_levelAssetsHandle.IsValid())
        {
            Addressables.Release(_levelAssetsHandle);
        }
    }
}

Asset Reference Types

using UnityEngine;
using UnityEngine.AddressableAssets;

public class TypedReferences : MonoBehaviour
{
    // Generic reference — loads as UnityEngine.Object
    [SerializeField] private AssetReference genericRef;

    // Typed references — type-safe in Inspector
    [SerializeField] private AssetReferenceGameObject prefabRef;
    [SerializeField] private AssetReferenceTexture2D textureRef;
    [SerializeField] private AssetReferenceSprite spriteRef;
    [SerializeField] private AssetReferenceT<AudioClip> audioRef;
    [SerializeField] private AssetReferenceT<ScriptableObject> dataRef;

    // AssetLabelReference — reference a label for batch loading
    [SerializeField] private AssetLabelReference enemyLabel;

    public async void LoadTypedAssets()
    {
        var prefab = await prefabRef.LoadAssetAsync<GameObject>().Task;
        var texture = await textureRef.LoadAssetAsync<Texture2D>().Task;
        var clip = await audioRef.LoadAssetAsync<AudioClip>().Task;
    }
}

Memory Leak Prevention

Common Mistakes

// BAD: Handle lost, can never release
public void LeakyLoad()
{
    Addressables.LoadAssetAsync<GameObject>("enemy"); // Handle not stored!
}

// BAD: Releasing too early
public async void TooEarlyRelease()
{
    var handle = Addressables.LoadAssetAsync<GameObject>("enemy");
    await handle.Task;
    var instance = Instantiate(handle.Result);
    Addressables.Release(handle); // Releases while instance still uses the asset!
}

// GOOD: Proper lifecycle
private AsyncOperationHandle<GameObject> _handle;
private GameObject _instance;

public async void ProperLoad()
{
    _handle = Addressables.LoadAssetAsync<GameObject>("enemy");
    await _handle.Task;
    _instance = Instantiate(_handle.Result);
}

private void OnDestroy()
{
    if (_instance != null) Destroy(_instance);
    if (_handle.IsValid()) Addressables.Release(_handle);
}

Remote Catalog Updates

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

public class CatalogUpdater : MonoBehaviour
{
    public async void CheckForUpdates()
    {
        var checkHandle = Addressables.CheckForCatalogUpdates(false);
        await checkHandle.Task;

        if (checkHandle.Status == AsyncOperationStatus.Succeeded)
        {
            List<string> catalogs = checkHandle.Result as List<string>;
            if (catalogs != null && catalogs.Count > 0)
            {
                Debug.Log($"Found {catalogs.Count} catalog updates");
                var updateHandle = Addressables.UpdateCatalogs(catalogs, false);
                await updateHandle.Task;
                Debug.Log("Catalogs updated successfully");
                Addressables.Release(updateHandle);
            }
        }
        Addressables.Release(checkHandle);
    }
}

Preloading Assets

Compartilhar X LinkedIn