Unity Addressables by juliankerignard/unity-skills
npx skills add https://github.com/juliankerignard/unity-skills --skill 'Unity Addressables'指导使用 Addressables 系统进行异步资源加载、分组组织、内存管理和远程内容(CDN/DLC)。涵盖从 Resources.Load 迁移、带进度条的预加载、引用计数以及避免内存泄漏的释放模式。
com.unity.addressables 包Addressables.LoadAssetAsync<T> 加载Comment charger cet asset ?
|
+-- Toujours en memoire, reference directe dans l'Inspector ?
| --> Reference directe [SerializeField] (pas besoin d'Addressables)
|
+-- Charge a la demande, connu au compile-time ?
| --> AssetReference dans l'Inspector + LoadAssetAsync
|
+-- Charge dynamiquement par label/nom ?
| --> Addressables.LoadAssetsAsync avec label
|
+-- Contenu telechargeable (DLC, patches) ?
| --> Remote group + catalog update
|
+-- Migration depuis Resources.Load ?
--> Marquer les assets comme Addressable, remplacer Resources.Load par LoadAssetAsync
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
Characters、Levels、UI、AudioCore(包含在构建中)、Optional(可下载)level1、boss、tutorial)using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
public class AssetLoader : MonoBehaviour
{
[SerializeField] private AssetReference prefabRef;
private AsyncOperationHandle<GameObject> handle;
public async Awaitable<GameObject> LoadAndInstantiateAsync()
{
handle = Addressables.LoadAssetAsync<GameObject>(prefabRef);
await handle.Task;
if (handle.Status == AsyncOperationStatus.Succeeded)
return Instantiate(handle.Result);
Debug.LogError($"Failed to load: {prefabRef}");
return null;
}
private void OnDestroy()
{
// CRITIQUE: toujours release le handle
if (handle.IsValid())
Addressables.Release(handle);
}
}
关键点:
AssetReference 避免硬编码字符串await handle.Task 等待加载完成handle.Result 前始终检查 handle.StatusOnDestroy 中 Release 以避免泄漏public class LabelLoader : MonoBehaviour
{
[SerializeField] private AssetLabelReference labelRef;
private AsyncOperationHandle<IList<GameObject>> handle;
public async Awaitable<IList<GameObject>> LoadAllAsync()
{
handle = Addressables.LoadAssetsAsync<GameObject>(labelRef, null);
await handle.Task;
if (handle.Status == AsyncOperationStatus.Succeeded)
return handle.Result;
Debug.LogError($"Failed to load label: {labelRef}");
return null;
}
private void OnDestroy()
{
if (handle.IsValid())
Addressables.Release(handle);
}
}
// AVANT (synchrone, tout en memoire au build)
var prefab = Resources.Load<GameObject>("Enemies/Goblin");
// APRES (async, charge a la demande)
var handle = Addressables.LoadAssetAsync<GameObject>("Enemies/Goblin");
await handle.Task;
var prefab = handle.Result;
// ... utiliser prefab ...
Addressables.Release(handle);
迁移步骤:
Resources/ 文件夹Resources/ 路径对应Resources.Load<T>(path) 替换为 Addressables.LoadAssetAsync<T>(address)Release()Resources/ 文件夹using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.ResourceProviders;
public class SceneLoader : MonoBehaviour
{
[SerializeField] private AssetReference sceneRef;
private AsyncOperationHandle<SceneInstance> sceneHandle;
public async Awaitable LoadSceneAsync()
{
sceneHandle = Addressables.LoadSceneAsync(sceneRef);
await sceneHandle.Task;
}
public async Awaitable UnloadSceneAsync()
{
if (sceneHandle.IsValid())
{
await Addressables.UnloadSceneAsync(sceneHandle).Task;
}
}
}
Addressables.Release(handle)AssetReference(避免硬编码字符串地址)handle.Status)InstantiateAsync 创建的对象使用 Addressables.ReleaseInstance() 而不是 Destroy()Resources.Load(使用 Addressables)AssetReferenceT<T> 来指定引用类型(AssetReferenceGameObject、AssetReferenceSprite 等)AssetLabelReference 而不是硬编码的标签字符串/perf-audit:检测内存泄漏和未释放的资源/unity-build-config:构建内容和远程目录/unity-code-gen:生成加载系统和资源管理器| 问题 | 解决方案 |
|---|---|
| "InvalidKeyException" | 地址或标签不存在。在 Addressables Groups 窗口中检查 |
| 内存泄漏 | 忘记调用 Release()。使用 Addressables Profiler(Event Viewer) |
| 构建不包含资源 | 资源不在任何组中,或该组未包含在构建中 |
| 加载缓慢 | 组过大。按用途拆分为子组 |
| "Cannot instantiate" | 资源不是预制体或加载失败(检查 Status) |
| "Exception during init" | Addressables 未初始化。先调用 Addressables.InitializeAsync() |
| 资源重复 | 一个资源在多个组中。使用 Build Report 检测 |
| 远程目录未更新 | 在启动时调用 CheckForCatalogUpdates 然后 UpdateCatalogs |
每周安装次数
–
代码仓库
GitHub 星标数
3
首次出现时间
–
安全审计
Guider l'utilisation du systeme Addressables pour le chargement d'assets asynchrone, l'organisation en groupes, la gestion memoire et le contenu distant (CDN/DLC). Couvre la migration depuis Resources.Load, le preloading avec progression, le reference counting et les patterns de release pour eviter les memory leaks.
com.unity.addressables installe via Package ManagerAddressables.LoadAssetAsync<T>Comment charger cet asset ?
|
+-- Toujours en memoire, reference directe dans l'Inspector ?
| --> Reference directe [SerializeField] (pas besoin d'Addressables)
|
+-- Charge a la demande, connu au compile-time ?
| --> AssetReference dans l'Inspector + LoadAssetAsync
|
+-- Charge dynamiquement par label/nom ?
| --> Addressables.LoadAssetsAsync avec label
|
+-- Contenu telechargeable (DLC, patches) ?
| --> Remote group + catalog update
|
+-- Migration depuis Resources.Load ?
--> Marquer les assets comme Addressable, remplacer Resources.Load par LoadAssetAsync
Characters, Levels, UI, AudioCore (inclus dans le build), Optional (telechargeable)level1, boss, tutorial)using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
public class AssetLoader : MonoBehaviour
{
[SerializeField] private AssetReference prefabRef;
private AsyncOperationHandle<GameObject> handle;
public async Awaitable<GameObject> LoadAndInstantiateAsync()
{
handle = Addressables.LoadAssetAsync<GameObject>(prefabRef);
await handle.Task;
if (handle.Status == AsyncOperationStatus.Succeeded)
return Instantiate(handle.Result);
Debug.LogError($"Failed to load: {prefabRef}");
return null;
}
private void OnDestroy()
{
// CRITIQUE: toujours release le handle
if (handle.IsValid())
Addressables.Release(handle);
}
}
Points cles :
AssetReference dans l'Inspector evite les magic stringsawait handle.Task pour attendre le chargementhandle.Status avant d'utiliser handle.ResultRelease dans OnDestroy pour eviter les leakspublic class LabelLoader : MonoBehaviour
{
[SerializeField] private AssetLabelReference labelRef;
private AsyncOperationHandle<IList<GameObject>> handle;
public async Awaitable<IList<GameObject>> LoadAllAsync()
{
handle = Addressables.LoadAssetsAsync<GameObject>(labelRef, null);
await handle.Task;
if (handle.Status == AsyncOperationStatus.Succeeded)
return handle.Result;
Debug.LogError($"Failed to load label: {labelRef}");
return null;
}
private void OnDestroy()
{
if (handle.IsValid())
Addressables.Release(handle);
}
}
// AVANT (synchrone, tout en memoire au build)
var prefab = Resources.Load<GameObject>("Enemies/Goblin");
// APRES (async, charge a la demande)
var handle = Addressables.LoadAssetAsync<GameObject>("Enemies/Goblin");
await handle.Task;
var prefab = handle.Result;
// ... utiliser prefab ...
Addressables.Release(handle);
Etapes de migration :
Resources/Resources/Resources.Load<T>(path) par Addressables.LoadAssetAsync<T>(address)Release() quand l'asset n'est plus necessaireResources/ une fois la migration termineeusing UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.ResourceProviders;
public class SceneLoader : MonoBehaviour
{
[SerializeField] private AssetReference sceneRef;
private AsyncOperationHandle<SceneInstance> sceneHandle;
public async Awaitable LoadSceneAsync()
{
sceneHandle = Addressables.LoadSceneAsync(sceneRef);
await sceneHandle.Task;
}
public async Awaitable UnloadSceneAsync()
{
if (sceneHandle.IsValid())
{
await Addressables.UnloadSceneAsync(sceneHandle).Task;
}
}
}
Addressables.Release(handle) quand l'asset n'est plus necessaireAssetReference dans l'Inspector (pas de string addresses en dur)handle.Status)Addressables.ReleaseInstance() au lieu de Destroy() pour les objets crees via InstantiateAsyncResources.Load dans un nouveau projet (utiliser Addressables)/perf-audit : detecter memory leaks et assets non release/unity-build-config : build content et remote catalog/unity-code-gen : generer loading system et asset managers| Probleme | Solution |
|---|---|
| "InvalidKeyException" | L'address ou le label n'existe pas. Verifier dans Addressables Groups window |
| Memory leak | Oubli de Release(). Utiliser le Profiler Addressables (Event Viewer) |
| Build ne contient pas l'asset | L'asset n'est dans aucun groupe ou le groupe n'est pas inclus dans le build |
| Chargement lent | Groupes trop gros. Splitter en sous-groupes par usage |
| "Cannot instantiate" | L'asset n'est pas un prefab ou le chargement a echoue (verifier Status) |
| "Exception during init" | Addressables pas initialise. Appeler Addressables.InitializeAsync() d'abord |
| Duplication d'assets | Un asset est dans plusieurs groupes. Utiliser le Build Report pour detecter |
| Remote catalog pas a jour | Appeler CheckForCatalogUpdates puis au lancement |
Weekly Installs
–
Repository
GitHub Stars
3
First Seen
–
Security Audits
Vue.js开发指南:最佳实践、组件设计与响应式编程核心原则
1,500 周安装
技能升级器:使用决策理论v5和RAG将任何技能升级为元技能
211 周安装
Claude技能开发指南:创建自定义MCP管道技能与元技能开发教程
211 周安装
色彩可访问性指南:WCAG对比度标准、色盲模拟与最佳实践
212 周安装
AgentOps技能转换器 - 一键将技能转换为Codex、Cursor等AI平台格式
212 周安装
Agile Skill Build:快速创建和扩展ace-skills的自动化工具,提升AI技能开发效率
1 周安装
LLM评估工具lm-evaluation-harness使用指南:HuggingFace模型基准测试与性能分析
212 周安装
AssetReferenceT<T> pour typer les references (AssetReferenceGameObject, AssetReferenceSprite, etc.)AssetLabelReference dans l'Inspector plutot que des strings de labelsUpdateCatalogs