← ClaudeAtlas

game-assets-memorylisted

管理游戏资源与内存时使用。加载/卸载、图集、包体、泄漏防治。
Wade-DevCode/awesome-coding-skills-cn · ★ 3 · AI & Automation · score 78
Install: claude install-skill Wade-DevCode/awesome-coding-skills-cn
# 资源与内存 ## 何时用 - 新增资源加载逻辑(模型、纹理、音效、配置表)之前。 - 发现内存持续增长、场景切换后内存不降、或 Profiler 显示某类资源异常堆积时。 - 接入新的资源管理系统(Addressables、AssetBundle、自研热更)前做方案评审时。 - 出现「卸载了但内存没降」「切场景崩溃」「包体超预算」等问题排查时。 ## 核心规则 ### 1. 大资源必须异步加载 **规则:** 纹理、音频、场景、模型等大资源一律走异步接口加载,绝不在主线程同步读取;加载期间必须有合适的 loading 表现,加载完成回调后再使用资源。 **为什么:** 最常犯的错是原型阶段用同步加载图方便,上线前"有时间再改"——结果积累了几十处同步加载,进游戏时主线程卡顿 2 秒,ANR 投诉爆仓。另一个坑:异步加载发起后立刻用资源(还没加载完),导致空引用崩溃或用到上一次缓存的错误资源。 **怎么做:** ```csharp // Unity 示例 // 反例 — 同步加载阻塞主线程 var tex = Resources.Load<Texture2D>("hero/sword"); // ❌ 主线程阻塞 // 正例 — 异步加载,回调中使用 IEnumerator LoadHeroAsync(string key, Action<GameObject> onLoaded) { var handle = Addressables.LoadAssetAsync<GameObject>(key); yield return handle; // ✅ 异步等待 if (handle.Status == AsyncOperationStatus.Succeeded) { onLoaded(handle.Result); // ✅ 加载完再用 } else { Debug.LogError($"加载失败: {key}"); } } ``` - 加载过程中显示 loading 进度条或骨骼屏;加载超时(如 10 秒)要有降级或报错逻辑,不能死等。 - 预加载(Preload)在合适时机(进房间动画期间)提前触发,不要等玩家操作时才开始加载。 --- ### 2. 引用计数与卸载时机必须明确 **规则:** 每个资源的生命周期(谁持有、何时释放)必须在接入时明确设计;场景切换时主动释放当前场景独占的资源,不依赖 GC 或引擎的"自动"回收。 **为什么:** 最典型的泄漏路径:战斗场景加载了 50 个怪物预制体的纹理,战斗结束切回大厅,没有主动 Release,Addressables 的引用计数没归零,纹理全留在内存里。打完十场战斗内存涨到崩溃。反向问题也有:卸载太激进,在某个地方还持有引用时就强制卸载,运行时出现粉色/错误材质。 **怎么做:** - 使用 Addressables/AssetBundle ��,每次 `LoadAssetAsync` 对应一次 `Release`,用 RAII 或引用计数封装保证配对。 - 场景切换时有明确的「场景资源卸载」阶段:先通知所有系统释放本场景资源引用,再触发 `UnloadUnusedAssets`。 - 共享资源(公共 UI 图集、常驻音效)单独管理,不随场景卸载;战斗专属资源随战斗结束卸载。 - 建立资源持有关系图(