写在前边
宗宝的独立游戏【穿越奇迹】现已上线:
- Cocos插件,
- 微信小游戏,
- 抖音小游戏,
- 头条小游戏,
- TapTap平台。
大家可以搜索游戏名称:穿越奇迹 进行游戏体验。欢迎大家为游戏提出宝贵的意见
商城源码 商城源码已更新,并开启限时折扣
正文
对于游戏来说,详细的资源加载进度展示是相当重要的。可以让玩家了解游戏加载的进度,避免了玩家长时间等待而感到沮丧或无聊。可以让玩家更好地了解游戏加载的时间和进度,更好地规划自己的时间,知道何时可以开始游戏,而不会中途离开或失去耐心。
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加载进度的实现方案。同理对于字节小游戏也是相同的逻辑,只需要简单进行调整。希望可以帮助到大家,欢迎大家一起讨论,一起进步。
写在最后
宗宝公众号:穿越的杨宗宝
宗宝微信:Carlos13207