您现在的位置是:首页 >学无止境 >creator-assetbundle分包网站首页学无止境
creator-assetbundle分包
title: creator-assetbundle分包
categories: Cocos2dx
tags: [creator, 分包, assetbundle]
date: 2023-04-10 15:55:22
comments: false
mathjax: true
toc: true
creator-assetbundle分包
前篇
- Asset Bundle 介绍 - https://docs.cocos.com/creator/manual/zh/asset/bundle.html
- 资源分包升级指南 - https://docs.cocos.com/creator/manual/zh/asset/subpackage-upgrade-guide.html
assetbundle 分包出现的需求是游戏存在多个模块组成, 大厅和子游戏, 类似 unity-模块化热更.md, 不需要进入大厅前, 将所有的子游戏都热更进来, 而是在进子游戏时, 热更对应子游戏的资源.
优先级
- https://docs.cocos.com/creator/manual/zh/asset/bundle.html#%E4%BC%98%E5%85%88%E7%BA%A7
预加载
- 加载与预加载 - https://docs.cocos.com/creator/manual/zh/asset/preload-load.html
bundle 资源分包实测
构建测试
-
构建面板 配置远程包
- 主包为远程包: 就是引擎内置的 bundle 和 自定义的 bundle 勾选了 配置为远程包 的都会防止在构建目录的 remote 目录下
-
测试两个 bundle
- ab001 目录配置为 bundle, 不勾选 配置为远程包
- ab002 目录配置为 bundle, 勾选 配置为远程包
-
构建 并打包 apk
- remote 目录是构建出来的包, 包含所有 bundle 勾选了配置远程选项,
apk 打进去 bundle 就是没有勾选配置远程选项
- remote 目录是构建出来的包, 包含所有 bundle 勾选了配置远程选项,
加载测试
-
首次进入, 会去远程地址下载 内置资源
-
首次加载动态资源
-
再次启动, 再次动态加载资源, 都不会发起 http 请求, 使用的本地缓存的资源
缓存文件都放在了这个目录下
-
修改了其中一个资源, 从新构建新的 remote
- f9974 就是这个 ab 的版本
-
加载 ab 的时候指定版本为 f9974
看到以下请求
发现只有 bundle 信息 (json + js) 和 被修改的资源及对应的 json 文件 (md5 发送变化) 才会发起 http 请求去下载新的内容, 未修改的资源还是使用缓存里的资源
-
新旧 remote 对比一下
- 版本记录文件 (cc.config.xxxx.json) 里, 只有被修改资源的 md5 变化了
bundle 代码分包实测 - 大厅+子游戏
-
以大厅和子游戏为例
-
cocos 支持将 ts/js 代码分包到 bundle 中, 不过必须遵循 子游戏分包 引用 大厅分包 的代码时, 大厅分包 的代码必须已经 load 到了内存中
-
大厅一般为通用模块, 脚本被 n 个子游戏所引用, 而不能是大厅去引用子游戏的脚本, 所需必须确保加载顺序是 大厅先加载, 然后子游戏引用
如果大厅去引用子游戏会报错:
JS: Error: Unable to instantiate chunks:///_virtual/子游戏.ts from chunks:///_virtual/大厅.ts
, 因为此时子游戏脚本并不在内存里 -
那么如何将大厅中的数据传递到子游戏中呢? 可以通过 子游戏的预制上去挂子游戏脚本, 大厅实例化这个预制时, 往 node 上随意数据, 在子游戏脚本的
start
中去获取这个数据
-
实测
-
分包结构
- 子游戏: ab002 是一个 bundle
- Pnl002 是用来被大厅实例化的一个预制, 上面挂上了子游戏脚本 TestAb002.ts
- 大厅: code 是在默认的 main bundle 下
- 子游戏: ab002 是一个 bundle
-
大厅的测试代码 GameMgr.ts
@ccclass() export class GameMgr extends Component { static hi: string async start() { console.log('--- GameMgr start') GameMgr.hi = "hello" ResMgr.Ins = new ResMgr() ResMgr.Ins.setBundleName("ab002") let parentGo = director.getScene().getChildByPath("Canvas/bx_loading_button_yellow") let prefabPath = "Pnl002" let go = await ResMgr.Ins.instantiateAsync(prefabPath, parentGo, "hello001") // 里面的实现会将实例化出来的 node 把 "hello001" 塞进去, 如 node["mydata"] = "hello001" LogUtil.D("--- load Pnl002 222") } }
-
子游戏测试代码 TestAb002.ts
@ccclass() export class TestAb002 extends Component { start() { LogUtil.D("--- TestAb002.run, name:", GameMgr.hi) LogUtil.D(`--- node name: ${this.node.name}, data: ${this.node["mydata"]}`) // 自定义数据一定要在 start 中获取 } }
-
打包测试, 正常运行
-
编译出来的 js 代码查看
分别在对应 bundle 的 index.js 中
- 看的出来子游戏引用大厅脚本时, 并没有吧对应的 js 编译进来, 只是引用, 这样就达到了子游戏代码分包的效果
踩坑
bundle 中不能内嵌 bundle
- https://forum.cocos.org/t/topic/146995/2