| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
- import { assetManager, JsonAsset, Asset, SpriteFrame, AnimationClip } from 'cc';
- import { sp } from 'cc';
- /**
- * Bundle资源加载器
- * 统一管理Asset Bundle的加载和资源获取
- */
- export class BundleLoader {
- private static instance: BundleLoader = null;
- private loadedBundles: Map<string, any> = new Map();
- private loadingPromises: Map<string, Promise<any>> = new Map();
- public static getInstance(): BundleLoader {
- if (!BundleLoader.instance) {
- BundleLoader.instance = new BundleLoader();
- }
- return BundleLoader.instance;
- }
- /**
- * 加载Bundle
- * @param bundleName Bundle名称
- * @returns Promise<Bundle>
- */
- public async loadBundle(bundleName: string): Promise<any> {
- // 如果已经加载过,直接返回
- if (this.loadedBundles.has(bundleName)) {
- return this.loadedBundles.get(bundleName);
- }
- // 如果正在加载,返回加载Promise
- if (this.loadingPromises.has(bundleName)) {
- return this.loadingPromises.get(bundleName);
- }
- // 开始加载Bundle
- const loadingPromise = new Promise<any>((resolve, reject) => {
- console.log(`[BundleLoader] 开始加载Bundle: ${bundleName}`);
- assetManager.loadBundle(bundleName, (err, bundle) => {
- if (err) {
- console.error(`[BundleLoader] 加载Bundle失败: ${bundleName}`, err);
- this.loadingPromises.delete(bundleName);
- reject(err);
- return;
- }
-
- console.log(`[BundleLoader] Bundle加载成功: ${bundleName}`);
- this.loadedBundles.set(bundleName, bundle);
- this.loadingPromises.delete(bundleName);
- resolve(bundle);
- });
- });
- this.loadingPromises.set(bundleName, loadingPromise);
- return loadingPromise;
- }
- /**
- * 从Bundle中加载资源
- * @param bundleName Bundle名称
- * @param resourcePath 资源路径(相对于Bundle根目录)
- * @param assetType 资源类型
- * @returns Promise<Asset>
- */
- public async loadAssetFromBundle<T extends Asset>(bundleName: string, resourcePath: string, assetType?: typeof Asset): Promise<T> {
- try {
- // 先确保Bundle已加载
- const bundle = await this.loadBundle(bundleName);
-
- return new Promise<T>((resolve, reject) => {
- console.log(`[BundleLoader] 从Bundle ${bundleName} 加载资源: ${resourcePath}`);
-
- if (assetType) {
- bundle.load(resourcePath, assetType, (err: Error, asset: T) => {
- if (err) {
- console.error(`[BundleLoader] 从Bundle ${bundleName} 加载资源失败: ${resourcePath}`, err);
- reject(err);
- return;
- }
- console.log(`[BundleLoader] 资源加载成功: ${bundleName}/${resourcePath}`);
- resolve(asset);
- });
- } else {
- bundle.load(resourcePath, (err: Error, asset: T) => {
- if (err) {
- console.error(`[BundleLoader] 从Bundle ${bundleName} 加载资源失败: ${resourcePath}`, err);
- reject(err);
- return;
- }
- console.log(`[BundleLoader] 资源加载成功: ${bundleName}/${resourcePath}`);
- resolve(asset);
- });
- }
- });
- } catch (error) {
- console.error(`[BundleLoader] 加载资源时发生错误: ${bundleName}/${resourcePath}`, error);
- throw error;
- }
- }
- /**
- * 从data Bundle加载JSON资源的便捷方法
- * @param resourcePath 资源路径(相对于data Bundle根目录)
- * @returns Promise<JsonAsset>
- */
- public async loadDataJson(resourcePath: string): Promise<JsonAsset> {
- return this.loadAssetFromBundle<JsonAsset>('data', resourcePath, JsonAsset);
- }
- /**
- * 从images Bundle加载图片资源的便捷方法
- * @param resourcePath 资源路径(相对于images Bundle根目录)
- * @returns Promise<Asset>
- */
- public async loadImage(resourcePath: string): Promise<Asset> {
- return this.loadAssetFromBundle('images', resourcePath);
- }
- /**
- * 从images Bundle加载SpriteFrame资源的便捷方法
- * @param resourcePath 资源路径(相对于images Bundle根目录)
- * @returns Promise<SpriteFrame>
- */
- public async loadSpriteFrame(resourcePath: string): Promise<SpriteFrame> {
- return this.loadAssetFromBundle<SpriteFrame>('images', resourcePath, SpriteFrame);
- }
- /**
- * 从Animation Bundle加载动画资源的便捷方法
- * @param resourcePath 资源路径(相对于Animation Bundle根目录)
- * @returns Promise<AnimationClip>
- */
- public async loadAnimation(resourcePath: string): Promise<AnimationClip> {
- return this.loadAssetFromBundle<AnimationClip>('Animation', resourcePath, AnimationClip);
- }
- /**
- * 从Animation Bundle加载骨骼动画数据
- * @param resourcePath 资源路径(相对于Bundle根目录)
- * @returns Promise<sp.SkeletonData>
- */
- public static async loadSkeletonData(resourcePath: string): Promise<sp.SkeletonData> {
- const instance = BundleLoader.getInstance();
- return instance.loadAssetFromBundle('Animation', resourcePath, sp.SkeletonData);
- }
- /**
- * 检查Bundle是否已加载
- * @param bundleName Bundle名称
- * @returns boolean
- */
- public isBundleLoaded(bundleName: string): boolean {
- return this.loadedBundles.has(bundleName);
- }
- /**
- * 获取已加载的Bundle
- * @param bundleName Bundle名称
- * @returns Bundle | null
- */
- public getLoadedBundle(bundleName: string): any {
- return this.loadedBundles.get(bundleName) || null;
- }
- /**
- * 释放Bundle资源
- * @param bundleName Bundle名称
- */
- public releaseBundle(bundleName: string): void {
- const bundle = this.loadedBundles.get(bundleName);
- if (bundle) {
- bundle.releaseAll();
- this.loadedBundles.delete(bundleName);
- console.log(`[BundleLoader] Bundle已释放: ${bundleName}`);
- }
- }
- /**
- * 释放所有Bundle资源
- */
- public releaseAllBundles(): void {
- for (const [bundleName, bundle] of this.loadedBundles) {
- bundle.releaseAll();
- }
- this.loadedBundles.clear();
- console.log('[BundleLoader] 所有Bundle已释放');
- }
- }
|