Cocos Creator 3.x 如何完美的获取远程Bundle加载进度

正文

3d8a11cec9e441cdcc75e628f297926f.png

对于游戏来说,详细的资源加载进度展示是相当重要的。可以让玩家了解游戏加载的进度,避免了玩家长时间等待而感到沮丧或无聊。可以让玩家更好地了解游戏加载的时间和进度,更好地规划自己的时间,知道何时可以开始游戏,而不会中途离开或失去耐心。

1.Bundle介绍

  • 从 v2.4 开始,Creator 正式支持 Asset Bundle 功能。

  • Asset Bundle 作为资源模块化工具,允许开发者按照项目需求将贴图、脚本、场景等资源划分在多个 Asset Bundle 中,然后在游戏运行过程中,按照需求去加载不同的 Asset Bundle,以减少启动时需要加载的资源数量,从而减少首次下载和加载游戏时所需的时间

  • Asset Bundle 可以按需求放置在不同地方,比如可以放在远程服务器、本地、或者小游戏平台的分包中

2.Bundle加载

assetManager.loadBundle('xxx', (err, bundle) => {
    bundle.load('xxx');
});

通过以上代码,我们可以对Bundle进行加载;

需要注意的是此加载非彼加载,什么意思呢?

  • 在通过 API 加载 Asset Bundle 时,引擎并没有加载 Asset Bundle 中的所有资源,而是加载 Asset Bundle 的 资源清单,以及包含的 所有脚本

也就是说,当我们调用了开头的loadBundle加载了Bundle后,如果使用到其中的某个资源,还需要单独对某个资源进行加载

bundle.load(`prefab`, Prefab, function (err, prefab) {
    let newNode = instantiate(prefab);
    director.getScene().addChild(newNode);
});

3.远程Bundle加载

来到了本文的关键部分

  • Bundle加载本身只是对资源清单和脚本进行加载,这个步骤其实并不会有太大的耗时,所以loadBundle接口并为提供加载进度的回调,但是前提是Bundle包是被存放再本地

  • 当Bundle包被存放在远程服务器时。我们在调用loadBundle时,中间多了一步下载,首先将Bundle包下载到了本地,然后再进行加载

由于不存在进度的回调监听,所以在实际调用loadBundle时我们没办法获得Bundle下载的实时进度,只能耐心等待其成功回调的触发。就和前边提到的,这个毫无明确数据显示的加载会导致大量的玩家没有耐心去等待,从而流失。

这种情况最常见的就是有包体大小限制的小游戏平台,大多数的资源都是存放在服务器的,所以加载远程Bundle,并可以完美的显示其加载进度就尤为重要。

在宗宝的游戏中,对微信小游戏和字节小游戏进行了适配,借助平台自身的API和Cocos现有的API来实现一套可以获取远程下载实时进度的方案:

public downLoadBundle(name: string, onProgress: (progress: number, writeByte: number, allByte: number) => void, onComplete: (isSuccess) => void): void {
  .....
}

1.初始化

  • 1.初始化Bundle的远程服务器路径

  • 2.初始化平台本地路径

  • 3.初始化本地记录本版号和当前项目使用到的最新版本号

let remoteUrl: string = `${assetManager.downloader.remoteServerAddress}remote/${name}`;
let savePath: string = wx.env.USER_DATA_PATH + "/gamecaches/" + name; // 微信本地路径
//本地版本
let localVersion: string = sys.localStorage.getItem(name);
//最新对应
let version: string = assetManager.downloader.bundleVers[name];

2.版本匹配

  • 1.进行版本匹配检测,如果相同,则本地已是最新版本,直接调用loadBundle进行加载

  • 2.不匹配,则服务器存在最新版本需要更新

if (version === localVersion) {
    // 已经是最新的版本了
    console.log(`最新版本  ${name} bunder ${version}`);
    this.loadBundle(savePath, onComplete);
} else {
  ...
}

3.清除旧版本

  • 1.如果存在旧版本Bundle,在更新新版本前,将旧的资源进行删除

wx.getFileSystemManager().rmdirSync(savePath, true);

4.更新Config文件

  • 1.下载config.json文件,下载成功后被存放在临时目录

let configFile: string = `/config.${version ? `${version}.` : ''}json`;
let downloadTask: any = wx.downloadFile({
  url: remoteUrl + configFile,
  success: (res) => {
      if (res.statusCode === 200) {
          if (onComplete) onComplete(res.tempFilePath);
      }
  },
  fail: (res) => {
      console.log(`下载  ${remoteUrl + configFile} 失败, err ${res}`);
      if (onComplete) onComplete(null);
  },
});
  • 2.将临时目录的config.json文件移至本地路径下

wx.getFileSystemManager().saveFileSync(file, savePath + configFile);
let data = wx.getFileSystemManager().readFileSync(savePath + configFile, "utf8");
configData = JSON.parse(data);

5.更新资源文件

在宗宝的游戏中,所有的远程资源都是在Cocos Creator中对Bundle的进行配置,压缩类型选择的是ZIP,所以只需要下载对应版本的zip资源文件

  • 1.对zip文件进行下载,下载成功后默认存放在临时目录

  • 2.监听下载进度,可以获取整个包体的字节大小,以及已下载的字节大小和进度

let resFile: string = `/res.${resVersion ? `${resVersion}.` : ''}zip`;
console.log(`下载res zip 文件 ${resFile}`);
let downloadTask: any = wx.downloadFile({
  url: remoteUrl + resFile,
  success: (res) => {
      if (res.statusCode === 200) {
          console.log(`下载  ${remoteUrl + resFile} 成功,临时目录:${res.tempFilePath}`);
          if (onComplete) onComplete(res.tempFilePath);
      }
  },
  fail: (res) => {
      console.log(`下载  ${remoteUrl + resFile} 失败, err ${res}`);
      if (onComplete) onComplete(null);
  },
});
downloadTask.onProgressUpdate((res) => {
  if (onProgress) onProgress(res.progress, res.totalBytesWritten, res.totalBytesExpectedToWrite);
});
  • 3.将临时目录下载zip资源移至与config.json相同的本地路径下

  • 4.所有资源下载成功,保存版本号

wx.getFileSystemManager().saveFileSync(file, savePath + resFile);
console.log(`bundle文件 ${name} 已经从 ${file} 移动到 ${savePath + resFile}`);
sys.localStorage.setItem(name, version);

6.加载本地路径下的Bundle包

assetManager.loadBundle(savePath, (err, bundle) => {
    if (err) {
        console.warn(`杨宗宝:load bundle ${path} task err, err msg:${err}...`);
        onComplete(false);
    } else {
        console.log(`杨宗宝:load bundle ${path} task success...`);
        onComplete(true);
    }
});

总结

以上是宗宝个人的一些经验,以及对于微信小游戏平台显示远程Bundle加载进度的实现方案。同理对于字节小游戏也是相同的逻辑,只需要简单进行调整即可。

希望宗宝的分享可以帮助到大家,欢迎大家一起讨论,一起进步。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值