cocos creator 教程:框架 - 资源管理
【muzzik 教程】:框架 - 资源管理
实现功能
-
asset (资源管理器)
-
资源加载接口整合
-
编辑器资源加载
-
资源生命周期管理
-
-
bundle (bundle 管理器)
-
bundle 加载/重载
-
scene 加载
-
bundle 管理单元
-
asset (资源管理器)
资源加载接口整合
统一本地/远程/编辑器
资源加载接口为 get/get_dir
编辑器资源加载
// path_s_ 格式为 "db://assets/xxx"
const uuid_s = await Editor.Message.request("asset-db", "query-uuid", path_s_);
cc.assetManager.loadAny({ uuid: uuid_s }, completed_f);
资源加载优化
- 短时间加载/释放
在游戏中经常会遇到短时间加载/释放同一资源,所以针对这点进行优化
- 加载资源后引用计数 + 2
- 重载 decRef,在引用计数为 1 时加入释放表,释放表间隔批量释放
-
未返回时加载相同资源
如果在加载资源还未返回时,再次加载相同路径的资源,那么 返回的资源对象不是同一个,会造成使用误导(因为引用计数也不相同),可能导致使用者误调用cc.assetManager.releaseAsset
强制释放,这时候另外一个资源如果还在使用就会导致报错,卡死- 解决方案:使用 Map 存储加载的资源对象,如果在加载完成后发现 Map 存在相同资源,则取出资源并 addRef 后替换资源对象
资源释放优化
- 重启游戏时清理资源
restart 时需要清理定时器,更新释放表,清理 bundle 未使用的资源
- 使用动态图集时也需要清理对应的纹理资源
bundle (bundle 管理器)
bundle 加载
很简答,封装 cc.assetManager.loadBundle
为异步函数即可
bundle 重载
由于引擎没有实现 bundle 重载后的脚本资源更新,所以需要我们自己做
/** 重新加载 bundle */
async reload(info: Partial<bundle_.bundle_info>): Promise<cc.AssetManager.Bundle | null> {
if (PREVIEW) {
return null;
}
await this._engine_init_task;
/** bundle 信息 */
const bundle_info: bundle_.bundle_info = new bundle_.bundle_info(info)!;
/** bundle 脚本表 */
const bundle_script_tab: Record<string, any> = {};
/** js 系统 */
const system_js = self["System"];
/** 脚本缓存表 */
const script_cache_tab: Record<string, any> = system_js[Reflect.ownKeys(system_js).find((v) => typeof v === "symbol")];
// 更新 bundle 信息
this.add(bundle_info);
// 初始化 bundle 脚本表
Object.keys(script_cache_tab).forEach((v_s) => {
const current = script_cache_tab[v_s];
const parent = script_cache_tab[v_s].p;
const child = parent.d;
if (!parent || !child || current.id !== parent.id) {
return;
}
const name_s = parent.id.slice((parent.id as string).lastIndexOf("/") + 1);
bundle_script_tab[name_s] = parent;
});
// 清理脚本缓存
{
const bundle_root = bundle_script_tab[bundle_info.bundle_s];
if (bundle_root) {
bundle_root.d.forEach((v: { id: string }) => {
/** 脚本名 */
const name_s = v.id.slice((v.id as string).lastIndexOf("/") + 1, v.id.length - 3);
/** ccclass */
const ccclass = cc.js.getClassByName(name_s);
// 注销组件
if (ccclass) {
cc.js.unregisterClass(ccclass);
}
delete script_cache_tab[v.id];
delete system_js["registerRegistry"][v.id];
});
delete script_cache_tab[bundle_root.id];
delete system_js["registerRegistry"][bundle_root.id];
}
}
// 清理 bundle 资源
{
const bundle = cc.assetManager.getBundle(bundle_info.bundle_s);
if (bundle) {
bundle.releaseAll();
cc.assetManager.removeBundle(bundle);
}
}
// 加载 bundle
return this.load(bundle_info);
}
scene 加载
/** switch_scene 配置 */
export class switch_scene_config {
constructor(init_?: Partial<switch_scene_config>) {
Object.assign(this, init_);
}
/** bundle名(getBundle 时使用) */
bundle_s = "resources";
/** 预加载 */
preload_b?: boolean;
/** 加载回调 */
progress_callback_f?: (finish_n: number, total_n: number, item?: cc.AssetManager.RequestItem) => void;
/** 加载前调用的函数 */
before_load_callback_f?: cc.Director.OnBeforeLoadScene;
/** 启动后调用的函数 */
launched_callback_f?: cc.Director.OnSceneLaunched;
/** 场景卸载后回调 */
unloaded_callback_f?: cc.Director.OnUnload;
}
bundle 管理单元
...
本文来自博客园,作者:Muzzik,转载请注明原文链接:https://www.cnblogs.com/muzzik/p/17099273.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步