Framework.ResMgr资源管理
This commit is contained in:
293
client/assets/scripts/Framework/ResMgr/ResMgr.ts
Normal file
293
client/assets/scripts/Framework/ResMgr/ResMgr.ts
Normal file
@@ -0,0 +1,293 @@
|
||||
import { Asset, AssetManager, assetManager, resources } from 'cc';
|
||||
|
||||
/**
|
||||
* 资源管理器
|
||||
* 职责:
|
||||
* - 统一管理资源加载
|
||||
* - 提供从bundle中按路径加载资源的接口
|
||||
* - 支持资源预加载
|
||||
* - 管理资源缓存和释放
|
||||
*/
|
||||
export class ResMgr {
|
||||
private static _instance: ResMgr | null = null;
|
||||
|
||||
/**
|
||||
* 资源缓存
|
||||
* key: bundleName:path
|
||||
* value: Asset
|
||||
*/
|
||||
private _cache: Map<string, Asset>;
|
||||
|
||||
/**
|
||||
* Bundle缓存
|
||||
* key: bundleName
|
||||
* value: AssetManager.Bundle
|
||||
*/
|
||||
private _bundles: Map<string, AssetManager.Bundle>;
|
||||
|
||||
/**
|
||||
* 构造函数(私有)
|
||||
*/
|
||||
private constructor() {
|
||||
this._cache = new Map<string, Asset>();
|
||||
this._bundles = new Map<string, AssetManager.Bundle>();
|
||||
|
||||
// 默认添加resources bundle
|
||||
this._bundles.set('resources', resources);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取单例
|
||||
*/
|
||||
static getInstance(): ResMgr {
|
||||
if (!this._instance) {
|
||||
this._instance = new ResMgr();
|
||||
}
|
||||
return this._instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Bundle
|
||||
* @param bundleName bundle名称
|
||||
*/
|
||||
private getBundle(bundleName: string): AssetManager.Bundle | null {
|
||||
// 从缓存中获取
|
||||
if (this._bundles.has(bundleName)) {
|
||||
return this._bundles.get(bundleName)!;
|
||||
}
|
||||
|
||||
// 使用 assetManager.getBundle() 方法获取已加载的 Bundle
|
||||
const bundle = assetManager.getBundle(bundleName);
|
||||
if (bundle) {
|
||||
this._bundles.set(bundleName, bundle);
|
||||
return bundle;
|
||||
}
|
||||
|
||||
console.error(`[ResMgr] Bundle "${bundleName}" 不存在`);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成缓存key
|
||||
*/
|
||||
private getCacheKey(bundleName: string, path: string): string {
|
||||
return `${bundleName}:${path}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载单个资源
|
||||
* @param bundleName bundle名称
|
||||
* @param path 资源路径
|
||||
* @param type 资源类型
|
||||
* @returns Promise<资源>
|
||||
*/
|
||||
load<T extends Asset>(
|
||||
bundleName: string,
|
||||
path: string,
|
||||
type: new (...args: any[]) => T
|
||||
): Promise<T> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const cacheKey = this.getCacheKey(bundleName, path);
|
||||
|
||||
// 检查缓存
|
||||
if (this._cache.has(cacheKey)) {
|
||||
const cached = this._cache.get(cacheKey) as T;
|
||||
console.log(`[ResMgr] 从缓存加载资源: ${path}`);
|
||||
resolve(cached);
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取bundle
|
||||
const bundle = this.getBundle(bundleName);
|
||||
if (!bundle) {
|
||||
reject(new Error(`Bundle "${bundleName}" 不存在`));
|
||||
return;
|
||||
}
|
||||
|
||||
// 加载资源
|
||||
console.log(`[ResMgr] 开始加载资源: ${bundleName}/${path}`);
|
||||
bundle.load(path, type, (err, asset) => {
|
||||
if (err) {
|
||||
console.error(`[ResMgr] 加载资源失败: ${bundleName}/${path}`, err);
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
|
||||
// 缓存资源
|
||||
this._cache.set(cacheKey, asset as Asset);
|
||||
console.log(`[ResMgr] 资源加载成功: ${bundleName}/${path}`);
|
||||
resolve(asset as T);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 预加载资源
|
||||
* @param bundleName bundle名称
|
||||
* @param path 资源路径
|
||||
* @param type 资源类型
|
||||
* @param onProgress 进度回调
|
||||
* @returns Promise<void>
|
||||
*/
|
||||
preload<T extends Asset>(
|
||||
bundleName: string,
|
||||
path: string,
|
||||
type: new (...args: any[]) => T,
|
||||
onProgress?: (finished: number, total: number) => void
|
||||
): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
// 获取bundle
|
||||
const bundle = this.getBundle(bundleName);
|
||||
if (!bundle) {
|
||||
reject(new Error(`Bundle "${bundleName}" 不存在`));
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`[ResMgr] 开始预加载资源: ${bundleName}/${path}`);
|
||||
|
||||
// 预加载资源
|
||||
bundle.preload(
|
||||
path,
|
||||
type,
|
||||
(finished, total) => {
|
||||
if (onProgress) {
|
||||
onProgress(finished, total);
|
||||
}
|
||||
},
|
||||
(err) => {
|
||||
if (err) {
|
||||
console.error(`[ResMgr] 预加载资源失败: ${bundleName}/${path}`, err);
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`[ResMgr] 资源预加载成功: ${bundleName}/${path}`);
|
||||
resolve();
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载目录
|
||||
* @param bundleName bundle名称
|
||||
* @param dir 目录路径
|
||||
* @param type 资源类型
|
||||
* @returns Promise<资源数组>
|
||||
*/
|
||||
loadDir<T extends Asset>(
|
||||
bundleName: string,
|
||||
dir: string,
|
||||
type: new (...args: any[]) => T
|
||||
): Promise<T[]> {
|
||||
return new Promise((resolve, reject) => {
|
||||
// 获取bundle
|
||||
const bundle = this.getBundle(bundleName);
|
||||
if (!bundle) {
|
||||
reject(new Error(`Bundle "${bundleName}" 不存在`));
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(`[ResMgr] 开始加载目录: ${bundleName}/${dir}`);
|
||||
|
||||
// 加载目录
|
||||
bundle.loadDir(dir, type, (err, assets) => {
|
||||
if (err) {
|
||||
console.error(`[ResMgr] 加载目录失败: ${bundleName}/${dir}`, err);
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
|
||||
// 缓存所有资源
|
||||
assets.forEach((asset) => {
|
||||
const path = `${dir}/${asset.name}`;
|
||||
const cacheKey = this.getCacheKey(bundleName, path);
|
||||
this._cache.set(cacheKey, asset);
|
||||
});
|
||||
|
||||
console.log(`[ResMgr] 目录加载成功: ${bundleName}/${dir}, 共 ${assets.length} 个资源`);
|
||||
resolve(assets as T[]);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 释放资源
|
||||
* @param bundleName bundle名称
|
||||
* @param path 资源路径
|
||||
*/
|
||||
release(bundleName: string, path: string): void {
|
||||
const cacheKey = this.getCacheKey(bundleName, path);
|
||||
|
||||
// 从缓存中移除
|
||||
if (this._cache.has(cacheKey)) {
|
||||
const asset = this._cache.get(cacheKey)!;
|
||||
this._cache.delete(cacheKey);
|
||||
|
||||
// 释放资源
|
||||
const bundle = this.getBundle(bundleName);
|
||||
if (bundle) {
|
||||
bundle.release(path);
|
||||
console.log(`[ResMgr] 释放资源: ${bundleName}/${path}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 释放目录资源
|
||||
* @param bundleName bundle名称
|
||||
* @param dir 目录路径
|
||||
*/
|
||||
releaseDir(bundleName: string, dir: string): void {
|
||||
// 释放所有以dir开头的缓存资源
|
||||
const prefix = `${bundleName}:${dir}`;
|
||||
const keysToDelete: string[] = [];
|
||||
|
||||
this._cache.forEach((_, key) => {
|
||||
if (key.startsWith(prefix)) {
|
||||
keysToDelete.push(key);
|
||||
}
|
||||
});
|
||||
|
||||
keysToDelete.forEach((key) => {
|
||||
this._cache.delete(key);
|
||||
});
|
||||
|
||||
// 释放目录
|
||||
const bundle = this.getBundle(bundleName);
|
||||
if (bundle) {
|
||||
bundle.releaseAll();
|
||||
console.log(`[ResMgr] 释放目录资源: ${bundleName}/${dir}, 共 ${keysToDelete.length} 个资源`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 释放所有资源
|
||||
*/
|
||||
releaseAll(): void {
|
||||
console.log(`[ResMgr] 释放所有资源, 共 ${this._cache.size} 个`);
|
||||
this._cache.clear();
|
||||
|
||||
// 释放所有bundle的资源
|
||||
this._bundles.forEach((bundle, name) => {
|
||||
if (name !== 'resources') {
|
||||
bundle.releaseAll();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取缓存大小
|
||||
*/
|
||||
getCacheSize(): number {
|
||||
return this._cache.size;
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空缓存(不释放资源)
|
||||
*/
|
||||
clearCache(): void {
|
||||
console.log(`[ResMgr] 清空缓存, 共 ${this._cache.size} 个`);
|
||||
this._cache.clear();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user