Files
rougelike-demo/client/assets/scripts/Framework/ResMgr/BundleProxy.ts

282 lines
8.2 KiB
TypeScript

import { Asset, AssetManager, assetManager } from 'cc';
import { ResProxy } from './ResProxy';
/**
* Bundle代理类
* 职责:
* - 异步加载Bundle
* - 管理Bundle的生命周期
* - 提供从Bundle加载资源的统一接口
*/
export class BundleProxy {
private _bundleName: string;
private _bundle: AssetManager.Bundle | null = null;
private _loading: Promise<AssetManager.Bundle> | null = null;
constructor(bundleName: string, bundle?: AssetManager.Bundle) {
this._bundleName = bundleName;
this._bundle = bundle || null;
}
/**
* 获取Bundle名称
*/
get bundleName(): string {
return this._bundleName;
}
/**
* 获取Bundle实例(同步)
*/
get bundle(): AssetManager.Bundle | null {
return this._bundle;
}
/**
* 异步加载Bundle
* @returns Promise<AssetManager.Bundle>
*/
async loadBundle(): Promise<AssetManager.Bundle> {
// 如果已经加载完成,直接返回
if (this._bundle) {
return this._bundle;
}
// 如果正在加载中,返回加载Promise
if (this._loading) {
return this._loading;
}
// 开始加载
this._loading = new Promise<AssetManager.Bundle>((resolve, reject) => {
console.log(`[BundleProxy] 开始加载Bundle: ${this._bundleName}`);
assetManager.loadBundle(this._bundleName, (err, bundle) => {
if (err) {
console.error(`[BundleProxy] 加载Bundle失败: ${this._bundleName}`, err);
this._loading = null;
reject(err);
return;
}
this._bundle = bundle;
this._loading = null;
console.log(`[BundleProxy] Bundle加载成功: ${this._bundleName}`);
resolve(bundle);
});
});
return this._loading;
}
/**
* 创建资源代理
* @param path 资源路径
* @param type 资源类型
* @returns ResProxy
*/
createResProxy<T extends Asset>(
path: string,
type: new (...args: any[]) => T
): ResProxy<T> {
return new ResProxy<T>(this, path, type);
}
/**
* 加载资源
* @param path 资源路径
* @param type 资源类型
* @returns Promise<资源>
*/
async loadRes<T extends Asset>(
path: string,
type: new (...args: any[]) => T
): Promise<T> {
const bundle = await this.loadBundle();
return new Promise((resolve, reject) => {
console.log(`[BundleProxy] 开始加载资源: ${this._bundleName}/${path}`);
bundle.load(path, type, (err, asset) => {
if (err) {
console.error(`[BundleProxy] 加载资源失败: ${this._bundleName}/${path}`, err);
reject(err);
return;
}
console.log(`[BundleProxy] 资源加载成功: ${this._bundleName}/${path}`);
resolve(asset as T);
});
});
}
/**
* 预加载资源
* @param path 资源路径
* @param type 资源类型
* @param onProgress 进度回调
* @returns Promise<void>
*/
async preload<T extends Asset>(
path: string,
type: new (...args: any[]) => T,
onProgress?: (finished: number, total: number) => void
): Promise<void> {
const bundle = await this.loadBundle();
return new Promise((resolve, reject) => {
console.log(`[BundleProxy] 开始预加载资源: ${this._bundleName}/${path}`);
bundle.preload(
path,
type,
(finished, total) => {
if (onProgress) {
onProgress(finished, total);
}
},
(err) => {
if (err) {
console.error(`[BundleProxy] 预加载资源失败: ${this._bundleName}/${path}`, err);
reject(err);
return;
}
console.log(`[BundleProxy] 资源预加载成功: ${this._bundleName}/${path}`);
resolve();
}
);
});
}
/**
* 加载目录
* @param dir 目录路径
* @param type 资源类型
* @param onProgress 进度回调
* @returns Promise<资源数组>
*/
async loadDir<T extends Asset>(
dir: string,
type: new (...args: any[]) => T,
onProgress?: (finished: number, total: number) => void
): Promise<T[]> {
const bundle = await this.loadBundle();
return new Promise((resolve, reject) => {
console.log(`[BundleProxy] 开始加载目录: ${this._bundleName}/${dir}`);
bundle.loadDir(
dir,
type,
(finished, total) => {
if (onProgress) {
onProgress(finished, total);
}
},
(err, assets) => {
if (err) {
console.error(`[BundleProxy] 加载目录失败: ${this._bundleName}/${dir}`, err);
reject(err);
return;
}
console.log(`[BundleProxy] 目录加载成功: ${this._bundleName}/${dir}, 共 ${assets.length} 个资源`);
resolve(assets as T[]);
}
);
});
}
/**
* 预加载目录
* @param dir 目录路径
* @param type 资源类型
* @param onProgress 进度回调
* @returns Promise<void>
*/
async preloadDir<T extends Asset>(
dir: string,
type: new (...args: any[]) => T,
onProgress?: (finished: number, total: number) => void
): Promise<void> {
const bundle = await this.loadBundle();
return new Promise((resolve, reject) => {
console.log(`[BundleProxy] 开始预加载目录: ${this._bundleName}/${dir}`);
bundle.preloadDir(
dir,
type,
(finished, total) => {
if (onProgress) {
onProgress(finished, total);
}
},
(err) => {
if (err) {
console.error(`[BundleProxy] 预加载目录失败: ${this._bundleName}/${dir}`, err);
reject(err);
return;
}
console.log(`[BundleProxy] 目录预加载成功: ${this._bundleName}/${dir}`);
resolve();
}
);
});
}
/**
* 释放资源
* @param path 资源路径
*/
release(path: string): void {
if (!this._bundle) {
console.warn(`[BundleProxy] Bundle未加载,无法释放资源: ${this._bundleName}/${path}`);
return;
}
this._bundle.release(path);
console.log(`[BundleProxy] 释放资源: ${this._bundleName}/${path}`);
}
/**
* 释放目录资源
* @param dir 目录路径
*/
releaseDir(dir: string): void {
if (!this._bundle) {
console.warn(`[BundleProxy] Bundle未加载,无法释放目录: ${this._bundleName}/${dir}`);
return;
}
// Cocos没有直接的releaseDir方法,需要手动释放目录下的资源
// 这里简化处理,实际使用时可能需要追踪加载的资源
console.log(`[BundleProxy] 释放目录资源: ${this._bundleName}/${dir}`);
}
/**
* 释放所有资源
*/
releaseAll(): void {
if (!this._bundle) {
console.warn(`[BundleProxy] Bundle未加载,无法释放所有资源: ${this._bundleName}`);
return;
}
this._bundle.releaseAll();
console.log(`[BundleProxy] 释放所有资源: ${this._bundleName}`);
}
/**
* 销毁Bundle
*/
destroy(): void {
if (this._bundle) {
this.releaseAll();
this._bundle = null;
}
this._loading = null;
}
}