From bbed2c5ebb3a91d96267045ecc84c260598c064b Mon Sep 17 00:00:00 2001 From: janing Date: Sun, 14 Dec 2025 23:36:20 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96Framework.ResMgr=E6=8A=BD?= =?UTF-8?q?=E8=B1=A1=E4=BB=A3=E7=90=86=E7=B1=BB=E4=BD=BF=E9=80=BB=E8=BE=91?= =?UTF-8?q?=E6=9B=B4=E6=95=B4=E6=B4=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../scripts/Framework/ResMgr/BundleProxy.ts | 281 ++++++++++++++ .../Framework/ResMgr/BundleProxy.ts.meta | 9 + .../scripts/Framework/ResMgr/README.md.meta | 11 + .../assets/scripts/Framework/ResMgr/ResMgr.ts | 365 ++++++++++-------- .../scripts/Framework/ResMgr/ResProxy.ts | 171 ++++++++ .../scripts/Framework/ResMgr/ResProxy.ts.meta | 9 + 6 files changed, 685 insertions(+), 161 deletions(-) create mode 100644 client/assets/scripts/Framework/ResMgr/BundleProxy.ts create mode 100644 client/assets/scripts/Framework/ResMgr/BundleProxy.ts.meta create mode 100644 client/assets/scripts/Framework/ResMgr/README.md.meta create mode 100644 client/assets/scripts/Framework/ResMgr/ResProxy.ts create mode 100644 client/assets/scripts/Framework/ResMgr/ResProxy.ts.meta diff --git a/client/assets/scripts/Framework/ResMgr/BundleProxy.ts b/client/assets/scripts/Framework/ResMgr/BundleProxy.ts new file mode 100644 index 0000000..aa0165f --- /dev/null +++ b/client/assets/scripts/Framework/ResMgr/BundleProxy.ts @@ -0,0 +1,281 @@ +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 | 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 + */ + async loadBundle(): Promise { + // 如果已经加载完成,直接返回 + if (this._bundle) { + return this._bundle; + } + + // 如果正在加载中,返回加载Promise + if (this._loading) { + return this._loading; + } + + // 开始加载 + this._loading = new Promise((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( + path: string, + type: new (...args: any[]) => T + ): ResProxy { + return new ResProxy(this, path, type); + } + + /** + * 加载资源 + * @param path 资源路径 + * @param type 资源类型 + * @returns Promise<资源> + */ + async loadRes( + path: string, + type: new (...args: any[]) => T + ): Promise { + 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 + */ + async preload( + path: string, + type: new (...args: any[]) => T, + onProgress?: (finished: number, total: number) => void + ): Promise { + 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( + dir: string, + type: new (...args: any[]) => T, + onProgress?: (finished: number, total: number) => void + ): Promise { + 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 + */ + async preloadDir( + dir: string, + type: new (...args: any[]) => T, + onProgress?: (finished: number, total: number) => void + ): Promise { + 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; + } +} diff --git a/client/assets/scripts/Framework/ResMgr/BundleProxy.ts.meta b/client/assets/scripts/Framework/ResMgr/BundleProxy.ts.meta new file mode 100644 index 0000000..cf2534a --- /dev/null +++ b/client/assets/scripts/Framework/ResMgr/BundleProxy.ts.meta @@ -0,0 +1,9 @@ +{ + "ver": "4.0.24", + "importer": "typescript", + "imported": true, + "uuid": "728bdb32-e73a-4fae-b942-b66412e95c6a", + "files": [], + "subMetas": {}, + "userData": {} +} diff --git a/client/assets/scripts/Framework/ResMgr/README.md.meta b/client/assets/scripts/Framework/ResMgr/README.md.meta new file mode 100644 index 0000000..cb377f6 --- /dev/null +++ b/client/assets/scripts/Framework/ResMgr/README.md.meta @@ -0,0 +1,11 @@ +{ + "ver": "1.0.1", + "importer": "text", + "imported": true, + "uuid": "3ab80465-bd0c-4023-b253-b019b2c686df", + "files": [ + ".json" + ], + "subMetas": {}, + "userData": {} +} diff --git a/client/assets/scripts/Framework/ResMgr/ResMgr.ts b/client/assets/scripts/Framework/ResMgr/ResMgr.ts index e6580c0..9f3c27a 100644 --- a/client/assets/scripts/Framework/ResMgr/ResMgr.ts +++ b/client/assets/scripts/Framework/ResMgr/ResMgr.ts @@ -1,39 +1,41 @@ import { Asset, AssetManager, assetManager, resources } from 'cc'; +import { BundleProxy } from './BundleProxy'; +import { ResProxy } from './ResProxy'; /** * 资源管理器 * 职责: - * - 统一管理资源加载 - * - 提供从bundle中按路径加载资源的接口 - * - 支持资源预加载 + * - 统一管理Bundle和资源 + * - 提供BundleProxy和ResProxy的创建和管理 + * - 提供便捷的资源加载接口 * - 管理资源缓存和释放 */ export class ResMgr { private static _instance: ResMgr | null = null; /** - * 资源缓存 - * key: bundleName:path - * value: Asset + * BundleProxy缓存 + * key: bundleName + * value: BundleProxy */ - private _cache: Map; + private _bundleProxies: Map; /** - * Bundle缓存 - * key: bundleName - * value: AssetManager.Bundle + * ResProxy缓存 + * key: bundleName:path + * value: ResProxy */ - private _bundles: Map; + private _resProxies: Map>; /** * 构造函数(私有) */ private constructor() { - this._cache = new Map(); - this._bundles = new Map(); + this._bundleProxies = new Map(); + this._resProxies = new Map>(); // 默认添加resources bundle - this._bundles.set('resources', resources); + this._bundleProxies.set('resources', new BundleProxy('resources', resources)); } /** @@ -46,27 +48,6 @@ export class 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 */ @@ -74,6 +55,55 @@ export class ResMgr { return `${bundleName}:${path}`; } + /** + * 获取或创建BundleProxy + * @param bundleName bundle名称 + * @returns BundleProxy + */ + getBundleProxy(bundleName: string): BundleProxy { + if (!this._bundleProxies.has(bundleName)) { + // 尝试从assetManager获取已加载的bundle + const bundle = assetManager.getBundle(bundleName); + const bundleProxy = new BundleProxy(bundleName, bundle || undefined); + this._bundleProxies.set(bundleName, bundleProxy); + } + return this._bundleProxies.get(bundleName)!; + } + + /** + * 加载Bundle + * @param bundleName bundle名称 + * @returns Promise + */ + async loadBundle(bundleName: string): Promise { + const bundleProxy = this.getBundleProxy(bundleName); + await bundleProxy.loadBundle(); + return bundleProxy; + } + + /** + * 获取或创建ResProxy + * @param bundleName bundle名称 + * @param path 资源路径 + * @param type 资源类型 + * @returns ResProxy + */ + getResProxy( + bundleName: string, + path: string, + type: new (...args: any[]) => T + ): ResProxy { + const cacheKey = this.getCacheKey(bundleName, path); + + if (!this._resProxies.has(cacheKey)) { + const bundleProxy = this.getBundleProxy(bundleName); + const resProxy = bundleProxy.createResProxy(path, type); + this._resProxies.set(cacheKey, resProxy); + } + + return this._resProxies.get(cacheKey)! as ResProxy; + } + /** * 加载单个资源 * @param bundleName bundle名称 @@ -81,44 +111,13 @@ export class ResMgr { * @param type 资源类型 * @returns Promise<资源> */ - load( + async load( bundleName: string, path: string, type: new (...args: any[]) => T ): Promise { - 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); - }); - }); + const resProxy = this.getResProxy(bundleName, path, type); + return resProxy.load(); } /** @@ -129,43 +128,14 @@ export class ResMgr { * @param onProgress 进度回调 * @returns Promise */ - preload( + async preload( bundleName: string, path: string, type: new (...args: any[]) => T, onProgress?: (finished: number, total: number) => void ): Promise { - 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(); - } - ); - }); + const resProxy = this.getResProxy(bundleName, path, type); + return resProxy.preload(onProgress); } /** @@ -173,42 +143,35 @@ export class ResMgr { * @param bundleName bundle名称 * @param dir 目录路径 * @param type 资源类型 + * @param onProgress 进度回调 * @returns Promise<资源数组> */ - loadDir( + async loadDir( bundleName: string, dir: string, - type: new (...args: any[]) => T + type: new (...args: any[]) => T, + onProgress?: (finished: number, total: number) => void ): Promise { - 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[]); - }); - }); + const bundleProxy = this.getBundleProxy(bundleName); + return bundleProxy.loadDir(dir, type, onProgress); + } + + /** + * 预加载目录 + * @param bundleName bundle名称 + * @param dir 目录路径 + * @param type 资源类型 + * @param onProgress 进度回调 + * @returns Promise + */ + async preloadDir( + bundleName: string, + dir: string, + type: new (...args: any[]) => T, + onProgress?: (finished: number, total: number) => void + ): Promise { + const bundleProxy = this.getBundleProxy(bundleName); + return bundleProxy.preloadDir(dir, type, onProgress); } /** @@ -219,17 +182,16 @@ export class ResMgr { 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}`); - } + // 从ResProxy缓存中获取并释放 + if (this._resProxies.has(cacheKey)) { + const resProxy = this._resProxies.get(cacheKey)!; + resProxy.release(); + // 可选:从缓存中移除ResProxy + // this._resProxies.delete(cacheKey); + } else { + // 如果没有ResProxy,直接从BundleProxy释放 + const bundleProxy = this.getBundleProxy(bundleName); + bundleProxy.release(path); } } @@ -239,55 +201,136 @@ export class ResMgr { * @param dir 目录路径 */ releaseDir(bundleName: string, dir: string): void { - // 释放所有以dir开头的缓存资源 + // 释放所有以dir开头的ResProxy const prefix = `${bundleName}:${dir}`; const keysToDelete: string[] = []; - this._cache.forEach((_, key) => { + this._resProxies.forEach((resProxy, key) => { if (key.startsWith(prefix)) { + resProxy.release(); keysToDelete.push(key); } }); + // 可选:从缓存中移除ResProxy keysToDelete.forEach((key) => { - this._cache.delete(key); + // this._resProxies.delete(key); }); - // 释放目录 - const bundle = this.getBundle(bundleName); - if (bundle) { - bundle.releaseAll(); - console.log(`[ResMgr] 释放目录资源: ${bundleName}/${dir}, 共 ${keysToDelete.length} 个资源`); - } + // 从BundleProxy释放目录 + const bundleProxy = this.getBundleProxy(bundleName); + bundleProxy.releaseDir(dir); + + console.log(`[ResMgr] 释放目录资源: ${bundleName}/${dir}, 共 ${keysToDelete.length} 个资源`); + } + + /** + * 释放Bundle的所有资源 + * @param bundleName bundle名称 + */ + releaseBundle(bundleName: string): void { + // 释放该Bundle下所有的ResProxy + const prefix = `${bundleName}:`; + const keysToDelete: string[] = []; + + this._resProxies.forEach((resProxy, key) => { + if (key.startsWith(prefix)) { + resProxy.release(); + keysToDelete.push(key); + } + }); + + // 从缓存中移除ResProxy + keysToDelete.forEach((key) => { + this._resProxies.delete(key); + }); + + // 释放BundleProxy的所有资源 + const bundleProxy = this.getBundleProxy(bundleName); + bundleProxy.releaseAll(); + + console.log(`[ResMgr] 释放Bundle所有资源: ${bundleName}, 共 ${keysToDelete.length} 个`); } /** * 释放所有资源 */ releaseAll(): void { - console.log(`[ResMgr] 释放所有资源, 共 ${this._cache.size} 个`); - this._cache.clear(); + console.log(`[ResMgr] 释放所有资源, 共 ${this._resProxies.size} 个ResProxy`); - // 释放所有bundle的资源 - this._bundles.forEach((bundle, name) => { + // 释放所有ResProxy + this._resProxies.forEach((resProxy) => { + resProxy.release(); + }); + this._resProxies.clear(); + + // 释放所有BundleProxy的资源(除了resources) + this._bundleProxies.forEach((bundleProxy, name) => { if (name !== 'resources') { - bundle.releaseAll(); + bundleProxy.releaseAll(); } }); } /** - * 获取缓存大小 + * 获取缓存的ResProxy数量 */ getCacheSize(): number { - return this._cache.size; + return this._resProxies.size; + } + + /** + * 获取缓存的BundleProxy数量 + */ + getBundleCount(): number { + return this._bundleProxies.size; } /** * 清空缓存(不释放资源) */ clearCache(): void { - console.log(`[ResMgr] 清空缓存, 共 ${this._cache.size} 个`); - this._cache.clear(); + console.log(`[ResMgr] 清空缓存, 共 ${this._resProxies.size} 个ResProxy`); + + // 清空所有ResProxy的缓存 + this._resProxies.forEach((resProxy) => { + resProxy.clearCache(); + }); + this._resProxies.clear(); + } + + /** + * 销毁Bundle + * @param bundleName bundle名称 + */ + destroyBundle(bundleName: string): void { + if (bundleName === 'resources') { + console.warn('[ResMgr] 不能销毁resources bundle'); + return; + } + + // 释放并移除该Bundle的所有ResProxy + const prefix = `${bundleName}:`; + const keysToDelete: string[] = []; + + this._resProxies.forEach((resProxy, key) => { + if (key.startsWith(prefix)) { + resProxy.release(); + keysToDelete.push(key); + } + }); + + keysToDelete.forEach((key) => { + this._resProxies.delete(key); + }); + + // 销毁BundleProxy + if (this._bundleProxies.has(bundleName)) { + const bundleProxy = this._bundleProxies.get(bundleName)!; + bundleProxy.destroy(); + this._bundleProxies.delete(bundleName); + } + + console.log(`[ResMgr] 销毁Bundle: ${bundleName}`); } } diff --git a/client/assets/scripts/Framework/ResMgr/ResProxy.ts b/client/assets/scripts/Framework/ResMgr/ResProxy.ts new file mode 100644 index 0000000..0105e76 --- /dev/null +++ b/client/assets/scripts/Framework/ResMgr/ResProxy.ts @@ -0,0 +1,171 @@ +import { Asset } from 'cc'; +import { BundleProxy } from './BundleProxy'; + +/** + * 资源代理类 + * 职责: + * - 封装单个资源的异步加载逻辑 + * - 管理资源的缓存状态 + * - 提供资源的加载、预加载、释放接口 + */ +export class ResProxy { + private _bundleProxy: BundleProxy; + private _path: string; + private _type: new (...args: any[]) => T; + private _asset: T | null = null; + private _loading: Promise | null = null; + private _preloading: Promise | null = null; + + constructor( + bundleProxy: BundleProxy, + path: string, + type: new (...args: any[]) => T + ) { + this._bundleProxy = bundleProxy; + this._path = path; + this._type = type; + } + + /** + * 获取资源路径 + */ + get path(): string { + return this._path; + } + + /** + * 获取Bundle名称 + */ + get bundleName(): string { + return this._bundleProxy.bundleName; + } + + /** + * 获取资源实例(同步) + */ + get asset(): T | null { + return this._asset; + } + + /** + * 是否已加载 + */ + get isLoaded(): boolean { + return this._asset !== null; + } + + /** + * 是否正在加载中 + */ + get isLoading(): boolean { + return this._loading !== null; + } + + /** + * 是否正在预加载中 + */ + get isPreloading(): boolean { + return this._preloading !== null; + } + + /** + * 加载资源 + * @returns Promise<资源> + */ + async load(): Promise { + // 如果已经加载完成,直接返回 + if (this._asset) { + console.log(`[ResProxy] 从缓存获取资源: ${this.bundleName}/${this._path}`); + return this._asset; + } + + // 如果正在加载中,返回加载Promise + if (this._loading) { + return this._loading; + } + + // 开始加载 + this._loading = this._bundleProxy.loadRes(this._path, this._type); + + try { + this._asset = await this._loading; + return this._asset; + } finally { + this._loading = null; + } + } + + /** + * 预加载资源 + * @param onProgress 进度回调 + * @returns Promise + */ + async preload(onProgress?: (finished: number, total: number) => void): Promise { + // 如果已经加载完成,直接返回 + if (this._asset) { + console.log(`[ResProxy] 资源已加载,无需预加载: ${this.bundleName}/${this._path}`); + return; + } + + // 如果正在预加载中,返回预加载Promise + if (this._preloading) { + return this._preloading; + } + + // 如果正在加载中,等待加载完成 + if (this._loading) { + await this._loading; + return; + } + + // 开始预加载 + this._preloading = this._bundleProxy.preload(this._path, this._type, onProgress); + + try { + await this._preloading; + } finally { + this._preloading = null; + } + } + + /** + * 释放资源 + */ + release(): void { + if (!this._asset) { + console.warn(`[ResProxy] 资源未加载,无法释放: ${this.bundleName}/${this._path}`); + return; + } + + this._bundleProxy.release(this._path); + this._asset = null; + console.log(`[ResProxy] 释放资源: ${this.bundleName}/${this._path}`); + } + + /** + * 清除缓存(不释放资源) + */ + clearCache(): void { + this._asset = null; + this._loading = null; + this._preloading = null; + } + + /** + * 重新加载资源 + * @returns Promise<资源> + */ + async reload(): Promise { + if (this._asset) { + this.release(); + } + return this.load(); + } + + /** + * 获取完整路径 + */ + getFullPath(): string { + return `${this.bundleName}/${this._path}`; + } +} diff --git a/client/assets/scripts/Framework/ResMgr/ResProxy.ts.meta b/client/assets/scripts/Framework/ResMgr/ResProxy.ts.meta new file mode 100644 index 0000000..7313e61 --- /dev/null +++ b/client/assets/scripts/Framework/ResMgr/ResProxy.ts.meta @@ -0,0 +1,9 @@ +{ + "ver": "4.0.24", + "importer": "typescript", + "imported": true, + "uuid": "e33b5325-cbc7-4082-9e05-093bb8478e2d", + "files": [], + "subMetas": {}, + "userData": {} +}