Unity 6.3 — Addressables¶
最后验证于: 2026-02-13
状态: 生产就绪
包: com.unity.addressables(Package Manager)
概述¶
Addressables 是 Unity 的高级资产管理系统,它用异步加载、远程内容交付和更好的内存控制取代了 Resources.Load()。
使用 Addressables 的场景:
- 异步资产加载(非阻塞)
- DLC 与远程内容
- 内存优化(按需加载/卸载)
- 资产依赖管理
- 包含大量资产的大型项目
不要将 Addressables 用于:
- 小型项目(额外开销不值得)
- 启动时立即需要的资产(请使用直接引用)
安装¶
通过 Package Manager 安装¶
Window > Package Manager- Unity Registry > 搜索 "Addressables"
- 安装
Addressables
核心概念¶
1. Addressable 资产¶
- 被标记为 "Addressable"(分配了唯一键)的资产
- 可在运行时通过键加载
2. 资产组¶
- 组织资产(例如 "UI"、"Weapons"、"Level1")
- 组决定构建设置(本地 vs 远程)
3. 异步加载¶
- 所有加载都是异步的(非阻塞)
- 返回
AsyncOperationHandle
4. 引用计数¶
- Addressables 会跟踪资产的使用情况
- 使用完成后必须手动释放资产
设置¶
1. 将资产标记为 Addressable¶
- 在 Project 窗口中选择资产
- 在 Inspector 中勾选 "Addressable"
- 分配键(例如 "Enemies/Goblin")
或通过脚本:
#if UNITY_EDITOR
using UnityEditor.AddressableAssets;
using UnityEditor.AddressableAssets.Settings;
AddressableAssetSettings.AddAssetEntry(guid, "MyAssetKey", "Default Local Group");
#endif
2. 创建组¶
Window > Asset Management > Addressables > Groups
- Default Local Group:随构建一起打包
- Remote Group:托管在服务器(CDN)上
基本加载¶
异步加载资产¶
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);
}
}
加载并实例化¶
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);
}
加载多个资产¶
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);
}
资产标签(Tags)¶
分配标签¶
Window > Asset Management > Addressables > Groups- 选择资产 > Inspector > Labels > 添加标签(例如 "Level1"、"UI")
按标签加载¶
远程内容(DLC)¶
设置远程组¶
- 创建新组:
Window > Addressables > Groups > Create New Group > Packed Assets - 组设置:
- Build Path:
ServerData/[BuildTarget] - Load Path:
http://yourcdn.com/content/[BuildTarget]
构建远程内容¶
Window > Asset Management > Addressables > Build > New Build > Default Build Script- 将
ServerData/文件夹上传到 CDN - 游戏将从远程服务器加载资产
预加载 / 缓存¶
下载依赖项¶
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);
}
检查下载大小¶
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);
}
内存管理¶
释放资产¶
// ✅ Always release when done
Addressables.Release(handle);
// ✅ For instantiated objects
Addressables.ReleaseInstance(gameObject);
检查引用计数¶
资产引用(Inspector 指定)¶
使用 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);
}
}
场景¶
加载 Addressable 场景¶
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¶
懒加载(按需加载)¶
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;
}
场景卸载时清理¶
void OnDestroy() {
// Release all handles
foreach (var handle in loadedAssets.Values) {
Addressables.Release(handle);
}
loadedAssets.Clear();
}
内容目录更新(实时更新)¶
检查目录更新¶
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¶
- 预加载 启动时频繁使用的资源
- 不再需要时立即释放资源
- 使用标签批量加载相关资源
- 缓存远程内容以供离线使用
调试¶
Addressables Event Viewer¶
Window > Asset Management > Addressables > Event Viewer
- 显示所有加载/释放操作
- 每个资源的内存使用情况
- 引用计数
Addressables Profiler¶
Window > Asset Management > Addressables > Profiler
- 实时资源使用情况
- Bundle 加载统计
从 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;
来源¶
- https://docs.unity3d.com/Packages/com.unity.addressables@2.0/manual/index.html
- https://learn.unity.com/tutorial/addressables
本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 cl/Claude-Code-Game-Studios