# 资源管理模块 (Framework/ResMgr) ## 📋 模块概述 统一的资源加载管理器,封装 Cocos Creator 的资源加载 API,支持从 bundle 中按路径加载资源,提供资源缓存和释放机制。 ## 🎯 核心特性 - ✅ 单例模式,全局统一管理 - ✅ 资源缓存机制 - ✅ Bundle 管理 - ✅ 支持单个资源加载 - ✅ 支持资源预加载 - ✅ 支持目录批量加载 - ✅ 资源释放管理 - ✅ 完整的日志输出 ## 🗂️ 文件结构 ``` Framework/ResMgr/ ├── ResMgr.ts # 资源管理器核心 ├── ResConfig.ts # 资源配置 └── ResMgrExample.ts # 使用示例 ``` ## 📘 核心类详解 ### ResMgr - 资源管理器 **职责**: 管理资源加载、缓存和释放 ```typescript class ResMgr { // 获取单例 static getInstance(): ResMgr; // 加载单个资源 load( bundleName: string, path: string, type: typeof Asset ): Promise; // 预加载资源(不实例化) preload( bundleName: string, path: string, type: typeof Asset, onProgress?: (finished: number, total: number) => void ): Promise; // 加载目录 loadDir( bundleName: string, dir: string, type: typeof Asset ): Promise; // 释放单个资源 release(bundleName: string, path: string): void; // 释放目录资源 releaseDir(bundleName: string, dir: string): void; // 释放所有资源 releaseAll(): void; // 获取缓存大小 getCacheSize(): number; } ``` ### ResConfig - 资源配置 **配置接口**: ```typescript // 资源加载配置 interface ResLoadConfig { showProgress?: boolean; // 是否显示加载进度 timeout?: number; // 加载超时时间(ms) retryCount?: number; // 失败重试次数 } // 预加载配置 interface PreloadConfig extends ResLoadConfig { onProgress?: (finished: number, total: number) => void; } // 常用资源路径 class ResPath { static readonly PREFAB = 'prefabs'; static readonly TEXTURE = 'textures'; static readonly AUDIO = 'audio'; static readonly SCENE = 'scenes'; } // 资源类型枚举 enum ResType { Prefab = 'Prefab', Texture = 'Texture', Audio = 'Audio', Scene = 'Scene' } ``` ## 📝 使用指南 ### 1. 加载单个资源 ```typescript import { ResMgr } from './Framework/ResMgr/ResMgr'; import { Prefab, SpriteFrame, AudioClip } from 'cc'; // 加载预制体 const prefab = await ResMgr.getInstance().load( 'resources', 'prefabs/Player', Prefab ); // 加载图片 const spriteFrame = await ResMgr.getInstance().load( 'resources', 'textures/icon', SpriteFrame ); // 加载音频 const audioClip = await ResMgr.getInstance().load( 'resources', 'audio/bgm', AudioClip ); ``` ### 2. 预加载资源 ```typescript import { ResMgr } from './Framework/ResMgr/ResMgr'; import { Prefab } from 'cc'; // 预加载资源(带进度回调) await ResMgr.getInstance().preload( 'resources', 'prefabs/Enemy', Prefab, (finished, total) => { const progress = (finished / total * 100).toFixed(0); console.log(`预加载进度: ${progress}%`); } ); // 预加载完成后再实际加载 const prefab = await ResMgr.getInstance().load( 'resources', 'prefabs/Enemy', Prefab ); ``` ### 3. 加载目录 ```typescript import { ResMgr } from './Framework/ResMgr/ResMgr'; import { SpriteFrame } from 'cc'; // 加载整个目录的资源 const sprites = await ResMgr.getInstance().loadDir( 'resources', 'textures/ui', SpriteFrame ); console.log(`加载了 ${sprites.length} 个图片资源`); // 使用加载的资源 for (const sprite of sprites) { console.log(`资源名称: ${sprite.name}`); } ``` ### 4. 释放资源 ```typescript import { ResMgr } from './Framework/ResMgr/ResMgr'; // 释放单个资源 ResMgr.getInstance().release('resources', 'prefabs/Player'); // 释放目录资源 ResMgr.getInstance().releaseDir('resources', 'textures/ui'); // 释放所有资源(场景切换时) ResMgr.getInstance().releaseAll(); ``` ### 5. 游戏场景资源管理 ```typescript // 场景资源管理器 class SceneResMgr { private _loadedRes: string[] = []; // 加载场景所需资源 async loadSceneRes(): Promise { const resMgr = ResMgr.getInstance(); // 加载角色 await resMgr.load('resources', 'prefabs/Player', Prefab); this._loadedRes.push('prefabs/Player'); // 加载敌人 await resMgr.load('resources', 'prefabs/Enemy', Prefab); this._loadedRes.push('prefabs/Enemy'); // 加载UI const uiSprites = await resMgr.loadDir( 'resources', 'textures/ui', SpriteFrame ); this._loadedRes.push('textures/ui'); console.log(`场景资源加载完成,共 ${this._loadedRes.length} 项`); } // 释放场景资源 releaseSceneRes(): void { const resMgr = ResMgr.getInstance(); for (const resPath of this._loadedRes) { if (resPath.endsWith('/')) { resMgr.releaseDir('resources', resPath); } else { resMgr.release('resources', resPath); } } this._loadedRes = []; console.log('场景资源已释放'); } } ``` ## 🔄 资源加载流程 ``` ResMgr.load(bundleName, path, type) ↓ 1. 检查缓存 ↓ 2. 如果已缓存,直接返回 ↓ 3. 通过 assetManager 加载 bundle ↓ 4. 从 bundle 加载资源 ↓ 5. 存入缓存 ↓ 6. 返回资源实例 ``` ## 📊 资源生命周期 ``` [请求加载资源] ↓ load() / preload() / loadDir() ↓ 资源加载到内存 ↓ 缓存资源引用 ↓ [使用资源] ↓ release() / releaseDir() / releaseAll() ↓ 资源从内存释放 ``` ## ⚠️ 注意事项 1. **Bundle 必须存在**: 确保 bundleName 对应的 bundle 已在 Cocos 中配置 2. **路径不含扩展名**: 资源路径不需要包含文件扩展名 3. **类型要匹配**: 加载时的 type 参数必须与实际资源类型匹配 4. **及时释放资源**: 不再使用的资源应及时释放,避免内存泄漏 5. **目录加载限制**: loadDir 只加载指定目录下的资源,不递归子目录 6. **缓存机制**: 相同路径的资源会被缓存,重复加载返回缓存实例 ## 🔍 调试技巧 ### 查看缓存大小 ```typescript const cacheSize = ResMgr.getInstance().getCacheSize(); console.log(`当前缓存资源数量: ${cacheSize}`); ``` ### 日志输出 ```typescript // ResMgr 内部包含详细日志: // [ResMgr] 加载资源: bundleName/path // [ResMgr] 从缓存加载: bundleName/path // [ResMgr] 释放资源: bundleName/path // [ResMgr] 释放目录: bundleName/dir // [ResMgr] 释放所有资源 ``` ### 常见问题 **问题1**: 资源加载失败 ```typescript // 检查: bundle 是否存在、路径是否正确、类型是否匹配 try { const prefab = await ResMgr.getInstance().load('resources', 'prefabs/Player', Prefab); } catch (error) { console.error('资源加载失败:', error); } ``` **问题2**: 内存占用过高 ```typescript // 解决: 及时释放不用的资源 ResMgr.getInstance().releaseAll(); ``` ## 💡 最佳实践 1. **场景切换时释放**: 切换场景时调用 `releaseAll()` 清理资源 2. **按需加载**: 不要一次性加载所有资源,按需加载 3. **预加载优化**: 对大资源使用 `preload()` 在空闲时预加载 4. **目录管理**: 合理组织资源目录结构,方便批量加载和释放 5. **资源复用**: 相同资源重复使用时,利用缓存机制避免重复加载 6. **错误处理**: 资源加载使用 try-catch 处理异常情况 ## 📚 常用资源类型 | 资源类型 | Cocos 类型 | 用途 | |---------|----------|------| | 预制体 | Prefab | 场景节点、UI 等 | | 图片 | SpriteFrame | 精灵图、UI图标 | | 音频 | AudioClip | 音效、背景音乐 | | 场景 | SceneAsset | 游戏场景 | | 字体 | Font | 文本渲染 | | 图集 | SpriteAtlas | 批量图片资源 | | 动画 | AnimationClip | 动画数据 | ## 🎯 应用场景 - ✅ 场景资源加载(角色、道具、环境等) - ✅ UI 资源加载(界面预制体、图标等) - ✅ 音频资源加载(背景音乐、音效等) - ✅ 关卡资源动态加载 - ✅ 资源热更新 - ✅ 分包加载