您现在的位置是:首页 >学无止境 >creator-assetbundle分包网站首页学无止境

creator-assetbundle分包

蝶泳奈何桥. 2023-05-30 20:00:02
简介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 资源分包实测

构建测试

  1. 构建面板 配置远程包

    image-20230415222003858

    • 主包为远程包: 就是引擎内置的 bundle 和 自定义的 bundle 勾选了 配置为远程包 的都会防止在构建目录的 remote 目录下
  2. 测试两个 bundle

    image-20230415222253574

    • ab001 目录配置为 bundle, 不勾选 配置为远程包
    • ab002 目录配置为 bundle, 勾选 配置为远程包
  3. 构建 并打包 apk

    image-20230415222445553

    • remote 目录是构建出来的包, 包含所有 bundle 勾选了配置远程选项,
      apk 打进去 bundle 就是没有勾选配置远程选项

加载测试

  1. 首次进入, 会去远程地址下载 内置资源

    image-20230415222709249

  2. 首次加载动态资源

    image-20230415222747452

  3. 再次启动, 再次动态加载资源, 都不会发起 http 请求, 使用的本地缓存的资源

    缓存文件都放在了这个目录下

    image-20230415222854837

  4. 修改了其中一个资源, 从新构建新的 remote

    image-20230415222930496

    • f9974 就是这个 ab 的版本
  5. 加载 ab 的时候指定版本为 f9974

    image-20230415223042264

    看到以下请求

    image-20230415223213286

    发现只有 bundle 信息 (json + js) 和 被修改的资源及对应的 json 文件 (md5 发送变化) 才会发起 http 请求去下载新的内容, 未修改的资源还是使用缓存里的资源

  6. 新旧 remote 对比一下

    image-20230415223525882

    • 版本记录文件 (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 中去获取这个数据

实测

  1. 分包结构

    image-20230421151624576

    • 子游戏: ab002 是一个 bundle
      • Pnl002 是用来被大厅实例化的一个预制, 上面挂上了子游戏脚本 TestAb002.ts
    • 大厅: code 是在默认的 main bundle 下
  2. 大厅的测试代码 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")
        }
    
    }
    
  3. 子游戏测试代码 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 中获取
        }
    }
    
    
  4. 打包测试, 正常运行

    image-20230421152931968

  5. 编译出来的 js 代码查看

    分别在对应 bundle 的 index.js

    image-20230421152429183

    • 看的出来子游戏引用大厅脚本时, 并没有吧对应的 js 编译进来, 只是引用, 这样就达到了子游戏代码分包的效果

踩坑

bundle 中不能内嵌 bundle

  • https://forum.cocos.org/t/topic/146995/2

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。