接上篇:小白也能写框架之【二、带颜色的日志管理器】
我们直接撸分包管理器的代码,我们都知道cocos默认分包加载只有是否完成回调,但是没进度回调
那我们自己撸一个。
一、新建assets\Core\Scripts\Managers\BundleMgr.ts,直接上代码:
import { assetManager, AssetManager } from "cc";
import { logMgr } from "./LogMgr";
/**
* 分包管理器
* 提供分包加载、获取、移除功能。
*/
class BundleMgr {
/** 私有构造函数,确保外部无法直接通过new创建实例 */
private constructor() {}
/** 单例实例 */
public static readonly instance: BundleMgr = new BundleMgr();
/**
* 获取指定分包,如果未加载则进行加载。
* @param nameOrUrl - 分包名称或URL。
* @param onProgress - 进度回调函数。
* @returns Promise<AssetManager.Bundle | null> - 加载完成后的Promise。
*/
public async getBundle(nameOrUrl: string, onProgress?: (progress: number) => void): Promise<AssetManager.Bundle | null> {
const bundle = assetManager.getBundle(nameOrUrl);
if (bundle) return bundle;
try {
const loadedBundle = await this.loadBundle(nameOrUrl);
if (onProgress) {
await this.loadAssetsWithProgress(loadedBundle, onProgress);
}
return loadedBundle;
} catch (error) {
logMgr.err(`分包 ${nameOrUrl} 加载失败`, error.message);
return null;
}
}
/**
* 加载指定分包。
* @param nameOrUrl - 分包名称或URL。
* @returns Promise<AssetManager.Bundle> - 加载完成后的Promise。
*/
private loadBundle(nameOrUrl: string): Promise<AssetManager.Bundle> {
return new Promise((resolve, reject) => {
assetManager.loadBundle(nameOrUrl, (err, loadedBundle) => {
if (err) {
reject(err);
} else {
resolve(loadedBundle);
}
});
});
}
/**
* 加载分包中的资源并提供进度反馈。
* @param bundle - 已加载的分包。
* @param onProgress - 进度回调函数。
* @returns Promise<void> - 加载完成后的Promise。
*/
private loadAssetsWithProgress(bundle: AssetManager.Bundle, onProgress: (progress: number) => void): Promise<void> {
return new Promise((resolve, reject) => {
const assets = bundle.getDirWithPath('');
const totalAssets = assets.length;
let loadedAssets = 0;
if (totalAssets === 0) {
onProgress(1);
resolve();
return;
}
assets.forEach((asset) => {
bundle.load(asset.path, (err) => {
if (err) {
reject(err);
return;
}
loadedAssets++;
onProgress(loadedAssets / totalAssets);
if (loadedAssets === totalAssets) {
resolve();
}
});
});
});
}
}
/** 分包管理器实例 */
export const bundleMgr = BundleMgr.instance;
二、代码解释
这段代码实现了一个分包管理器,使用 TypeScript 编写,主要用于管理和加载游戏或应用程序中的分包资源。以下是对其主要功能和结构的简要介绍:
-
BundleMgr 类:这是分包管理器类,负责加载和管理分包资源。它具有以下特点:
-
单例模式:通过私有构造函数和静态实例
instance实现,确保整个应用程序中只有一个BundleMgr实例。 -
获取分包:
getBundle方法用于获取指定的分包。如果分包尚未加载,则会进行加载。该方法返回一个Promise,在加载完成后返回AssetManager.Bundle或null。 -
加载分包:
loadBundle方法负责实际加载分包,并返回一个Promise,在加载完成后返回AssetManager.Bundle。 -
进度反馈:
loadAssetsWithProgress方法用于加载分包中的资源,并通过回调函数提供加载进度反馈。它计算已加载资源的比例,并在每次资源加载完成时调用进度回调。
-
单例模式:通过私有构造函数和静态实例
-
错误处理:在加载过程中,如果发生错误,会使用
logMgr记录错误信息,确保问题可以被及时发现和解决。 -
bundleMgr 导出:通过导出
bundleMgr实例,其他模块可以直接使用这个单例来管理分包资源。
这个分包管理器的设计使得分包资源的加载更加高效和可控,特别是在需要动态加载大量资源的游戏或应用程序中,提供了良好的用户体验和资源管理能力。
三、继续映射到全局,接上篇文章,我们导出映射到app
四、测试代码
1、我们随便新建一个分包,包含一个空的预制体方便测试,如图:
2、assets\App\Main.ts测试代码:
import { _decorator, Component, Node } from 'cc';
const { ccclass, property } = _decorator;
@ccclass('Main')
export class Main extends Component {
private testNum: number = 1314;
private testStr: string = 'cocos';
// 加载
onLoad() {
app.bundle.getBundle('TestBundle', this.testLoad)
.then((bundle) => {
if (bundle) {
app.log.info('分包加载成功');
}
});
}
// 开始
start() {
this.testLog();
}
// 日志测试
testLog() {
app.log.debug('我是日志1');
app.log.info('我是日志2');
app.log.warn('我是日志3');
app.log.err('我是日志4');
app.log.debug('打印数字变量:', this.testNum);
app.log.warn('打印文本变量:', this.testStr);
}
// 分包进度
testLoad(progress: number) {
app.log.info('分包加载进度', progress);
}
}
五、测试效果:
下一篇预告:小白也能写框架之【四、带加密的数据管理器】





一般不会这么做吧
