Unity 6.3 — Addressables
Unity 6.3 — Addressables
Last verified: 2026-02-13
Status: Production-Ready
Package: com.unity.addressables (Package Manager)
Overview
Addressables is Unity's advanced asset management system that replaces Resources.Load()
with async loading, remote content delivery, and better memory control.
Use Addressables for:
- Async asset loading (non-blocking)
- DLC and remote content
- Memory optimization (load/unload on demand)
- Asset dependency management
- Large projects with many assets
DON'T use Addressables for:
- Tiny projects (overhead not worth it)
- Assets needed immediately at startup (use direct references)
Installation
Install via Package Manager
Window > Package Manager- Unity Registry > Search "Addressables"
- Install
Addressables
Core Concepts
1. Addressable Assets
- Assets marked as "Addressable" (assigned unique keys)
- Can be loaded by key at runtime
2. Asset Groups
- Organize assets (e.g., "UI", "Weapons", "Level1")
- Groups determine build settings (local vs remote)
3. Async Loading
- All loading is async (non-blocking)
- Returns
AsyncOperationHandle
4. Reference Counting
- Addressables tracks asset usage
- Must manually release assets when done
Setup
1. Mark Assets as Addressable
- Select asset in Project window
- Inspector > Check "Addressable"
- Assign key (e.g., "Enemies/Goblin")
OR via script:
#if UNITY_EDITOR
using UnityEditor.AddressableAssets;
using UnityEditor.AddressableAssets.Settings;
AddressableAssetSettings.AddAssetEntry(guid, "MyAssetKey", "Default Local Group");
#endif
2. Create Groups
Window > Asset Management > Addressables > Groups
- Default Local Group: Bundled with build
- Remote Group: Hosted on server (CDN)
Basic Loading
Load Asset Async
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
public class AssetLoader : MonoBehaviour {
async void Start() {
// ✅ Load asset asynchronously
AsyncOperationHandle<GameObject> handle = Addressables.LoadAssetAsync<GameObject>("Enemies/Goblin");
await handle.Task;
if (handle.Status == AsyncOperationStatus.Succeeded) {
GameObject prefab = handle.Result;
Instantiate(prefab);
} else {
Debug.LogError("Failed to load asset");
}
// ⚠️ IMPORTANT: Release when done
Addressables.Release(handle);
}
}
Load and Instantiate
async void SpawnEnemy() {
// ✅ Load and instantiate in one step
AsyncOperationHandle<GameObject> handle = Addressables.InstantiateAsync("Enemies/Goblin");
await handle.Task;
GameObject enemy = handle.Result;
// Use enemy...
// ✅ Release when destroying
Addressables.ReleaseInstance(enemy);
}
Load Multiple Assets
async void LoadAllWeapons() {
// Load all assets with label "Weapons"
AsyncOperationHandle<IList<GameObject>> handle = Addressables.LoadAssetsAsync<GameObject>("Weapons", null);
await handle.Task;
foreach (var weapon in handle.Result) {
Debug.Log($"Loaded: {weapon.name}");
}
Addressables.Release(handle);
}
Asset Labels (Tags)
Assign Labels
Window > Asset Management > Addressables > Groups- Select asset > Inspector > Labels > Add label (e.g., "Level1", "UI")
Load by Label
// Load all assets with label "Level1"
Addressables.LoadAssetsAsync<GameObject>("Level1", null);
Remote Content (DLC)
Setup Remote Groups
- Create new group:
Window > Addressables > Groups > Create New Group > Packed Assets - Group Settings:
- Build Path:
ServerData/[BuildTarget] - Load Path:
http://yourcdn.com/content/[BuildTarget]
- Build Path:
Build Remote Content
Window > Asset Management > Addressables > Build > New Build > Default Build Script- Upload
ServerData/folder to CDN - Game loads assets from remote server
Preloading / Caching
Download Dependencies
async void PreloadLevel() {
// Download all assets in group without loading into memory
AsyncOperationHandle handle = Addressables.DownloadDependenciesAsync("Level1");
await handle.Task;
// Now "Level1" assets are cached, load instantly
Addressables.Release(handle);
}
Check Download Size
async void CheckDownloadSize() {
AsyncOperationHandle<long> handle = Addressables.GetDownloadSizeAsync("Level1");
await handle.Task;
long sizeInBytes = handle.Result;
Debug.Log($"Download size: {sizeInBytes / (1024 * 1024)} MB");
Addressables.Release(handle);
}
Memory Management
Release Assets
// ✅ Always release when done
Addressables.Release(handle);
// ✅ For instantiated objects
Addressables.ReleaseInstance(gameObject);
Check Reference Count
// Addressables uses reference counting
// Asset is unloaded when refCount == 0
Asset References (Inspector-Assigned)
Use AssetReference
using UnityEngine.AddressableAssets;
public class EnemySpawner : MonoBehaviour {
// ✅ Assign in Inspector (drag & drop)
public AssetReference enemyPrefab;
async void SpawnEnemy() {
AsyncOperationHandle<GameObject> handle = enemyPrefab.InstantiateAsync();
await handle.Task;
GameObject enemy = handle.Result;
// Use enemy...
enemyPrefab.ReleaseInstance(enemy);
}
}
Scenes
Load Addressable Scene
using UnityEngine.SceneManagement;
async void LoadScene() {
AsyncOperationHandle<SceneInstance> handle = Addressables.LoadSceneAsync("MainMenu", LoadSceneMode.Additive);
await handle.Task;
SceneInstance sceneInstance = handle.Result;
// Scene loaded
// Unload scene
await Addressables.UnloadSceneAsync(handle).Task;
}
Common Patterns
Lazy Loading (Load on Demand)
Dictionary<string, AsyncOperationHandle<GameObject>> loadedAssets = new();
async Task<GameObject> GetAsset(string key) {
if (!loadedAssets.ContainsKey(key)) {
var handle = Addressables.LoadAssetAsync<GameObject>(key);
await handle.Task;
loadedAssets[key] = handle;
}
return loadedAssets[key].Result;
}
Cleanup on Scene Unload
void OnDestroy() {
// Release all handles
foreach (var handle in loadedAssets.Values) {
Addressables.Release(handle);
}
loadedAssets.Clear();
}
Content Catalog Updates (Live Updates)
Check for Catalog Updates
async void CheckForUpdates() {
AsyncOperationHandle<List<string>> handle = Addressables.CheckForCatalogUpdates();
await handle.Task;
if (handle.Result.Count > 0) {
Debug.Log("Updates available");
await Addressables.UpdateCatalogs(handle.Result).Task;
}
Addressables.Release(handle);
}
Performance Tips
- Preload frequently used assets at startup
- Release assets immediately when not needed
- Use labels to batch-load related assets
- Cache remote content for offline use
Debugging
Addressables Event Viewer
Window > Asset Management > Addressables > Event Viewer
- Shows all load/release operations
- Memory usage per asset
- Reference counts
Addressables Profiler
Window > Asset Management > Addressables > Profiler
- Real-time asset usage
- Bundle loading stats
Migration from Resources
// ❌ OLD: Resources.Load (synchronous, blocks frame)
GameObject prefab = Resources.Load<GameObject>("Enemies/Goblin");
// ✅ NEW: Addressables (async, non-blocking)
var handle = await Addressables.LoadAssetAsync<GameObject>("Enemies/Goblin").Task;
GameObject prefab = handle.Result;