环境说明:
1、CocosCreator2.4.12
2、Windows/Mac环境下安卓需要配置环境
3、安装nodejs环境用于生成版本更新文件
4、Cocos官网下载CocosDashBoard ==>https://www.cocos.com/creator-download
热更新流程图:
热更新流程.jpg
1、创建CocosCreator热更新测试项目工程
2、关键代码说明:
初始化AssetsManager
protected onLoad(): void {
this._stotagePath = this.getCacheRootPath();
console.log(TAG, `远程版本缓存路径:${this._stotagePath}`);
this._hallAssetsMgr = new jsb.AssetsManager('', this._stotagePath, this.versionCompareHandle);
this._hallAssetsMgr.setVerifyCallback(this.setVerifyCallback.bind(this));
}
setVerifyCallback(path, asset) {
let compressed = asset.compressed;
let expectedMD5 = asset.md5;
let relativePath = asset.path;
let size = asset.size;
console.log("assetPath", path)
console.log("assetSize:", size);
if (compressed) {
this.toolTipslabel.string = "检查压缩 : " + relativePath;
return true;
} else {
this.toolTipslabel.string = "检查压缩 : " + relativePath + ' (' + expectedMD5 + ')';
return true;
}
}
versionCompareHandle(versionA: string, versionB: string) {
console.log(`当前版本 : ${versionA} , 远程版本 : ${versionB}`);
let vA = versionA.split('.');
let vB = versionB.split('.');
for (let i = 0; i < vA.length && i < vB.length; ++i) {
let a = parseInt(vA[I]);
let b = parseInt(vB[I]);
if (a === b) {
continue;
}
else {
return -1;
}
}
if (vB.length > vA.length) {
return -1;
}
return 0;
}
检查是否可进行更新
public doCheckUpdate() {
if (this._updating) {
return;
}
let url = this.hallMainifestUrl.nativeUrl;
console.log(TAG, `<checkUpdate> 原包版本信息url: ${this.hallMainifestUrl.nativeUrl}`);
if (this._hallAssetsMgr.getState() === jsb.AssetsManager.State.UNINITED) {
if (cc.loader.md5Pipe) {
url = cc.loader.md5Pipe.transformURL(url);
}
this._hallAssetsMgr.loadLocalManifest(url);
}
if (!this._hallAssetsMgr.getLocalManifest() || !this._hallAssetsMgr.getLocalManifest().isLoaded()) {
this.toolTipslabel.string = '加载本地manifest文件失败';
return;
}
this._hallAssetsMgr.setEventCallback(this.checkUpdateCallback.bind(this));
this._hallAssetsMgr.checkUpdate();
this._updating = true;
}
执行热更新操作
public doHotUpdate() {
if (this._hallAssetsMgr && !this._updating) {
this._hallAssetsMgr.setEventCallback(this.updateCallback.bind(this));
if (this._hallAssetsMgr.getState() === jsb.AssetsManager.State.UNINITED) {
let url = this.hallMainifestUrl.nativeUrl;
if (cc.loader.md5Pipe) {
url = cc.loader.md5Pipe.transformURL(url);
}
this._hallAssetsMgr.loadLocalManifest(url);
}
this._hallAssetsMgr.update();
this._updating = true;
}
}
代码详细
/**
* @Description: 热更新回调函数
* @Date: 2024-01-16 11:50:06
* @Author: fanlinsong add
* @param {*} event
* @return {*}
*/
private updateCallback(event) {
console.log(TAG, "<updateCallback> 热更回调");
let isUpdateFinished = false;
let needRestart = false;
let failed = false;
let evtMsg = event.getMessage();
if (evtMsg) {
this.toolTipslabel.string = 'Updated file: ' + evtMsg;
}
switch (event.getEventCode()) {
case jsb.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST:
this.toolTipslabel.string = '没有本地manifest文件,跳过热更.';
failed = true;
break;
case jsb.EventAssetsManager.UPDATE_PROGRESSION:
let percent = event.getPercent();
if (isNaN(percent)) {
return;
}
console.log(TAG, `<updateCallback> ${event.getDownloadedBytes()} / ${event.getTotalBytes()} (已下载大小/大小总数)`);
console.log(TAG, `<updateCallback> ${event.getDownloadedFiles()} / ${event.getTotalFiles()} (已下载文件数量/资源总数)`);
console.log(TAG, `<updateCallback> 当前进度百分比 percent : ${event.getPercent()}`);
console.log(TAG, `<updateCallback> 当前进度文件百分比 percent by file : ${event.getPercentByFile()}`);
console.log(TAG, "当前下载文件数: ", event.getDownloadedFiles());
console.log(TAG, "总文件数: ", event.getTotalFiles());
let msg = event.getMessage();
if (msg) {
this.toolTipslabel.string = '更新的文件:: ' + msg;
}
break;
case jsb.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST:
case jsb.EventAssetsManager.ERROR_PARSE_MANIFEST:
this.toolTipslabel.string = '下载远程manifest文件失败,跳过热更.';
console.log(TAG, `<updateCallback> ==> 下载远程manifest文件失败,跳过热更. | ${event.getMessage()}`);
failed = true;
break;
case jsb.EventAssetsManager.ALREADY_UP_TO_DATE:
this.toolTipslabel.string = '已经更新到远程最新版本.';
console.log(TAG, `<updateCallback> ==> 已经更新到远程最新版本. | ${event.getMessage()}`);
isUpdateFinished = true;
failed = true;
break;
case jsb.EventAssetsManager.UPDATE_FINISHED:
this.toolTipslabel.string = '更新完成,即将重启游戏. ' + event.getMessage();
console.log(TAG, `<updateCallback> ==> 更新完成,即将重启游戏. | ${event.getMessage()}`);
needRestart = true;
isUpdateFinished = true;
break;
case jsb.EventAssetsManager.UPDATE_FAILED:
this.toolTipslabel.string = '更新失败. ' + event.getMessage();
console.log(TAG, `<updateCallback> ==> 更新失败. | ${event.getMessage()}`);
this._updating = false;
break;
case jsb.EventAssetsManager.ERROR_UPDATING:
this.toolTipslabel.string = 'Asset 更新错误: ' + event.getAssetId() + ', ' + event.getMessage();
console.log(TAG, `<updateCallback> ==> Asset 更新错误: | assetId: ${event.getAssetId()} | ${event.getMessage()}`);
break;
case jsb.EventAssetsManager.ERROR_DECOMPRESS:
this.toolTipslabel.string = event.getMessage();
break;
default:
break;
}
let state = this._hallAssetsMgr.getState();
let evtPercent = (isNaN(event.getPercent()) ? 0 : event.getPercent());
let info: CustomUpdateDownLoad = {
downloadedBytes: event.getDownloadedBytes(),
totalBytes: event.getTotalBytes(),
downloadedFiles: event.getDownloadedFiles(),
totalFiles: event.getTotalFiles(),
percent: (isUpdateFinished ? 1 : evtPercent),
percentByFile: event.getPercentByFile(),
code: event.getEventCode(),
state: Number(state),
needRestart: isUpdateFinished,
};
this.notifyUpdateProgressFunc(info.percent, info);
if (failed) {
if (this._hallAssetsMgr) {
this._hallAssetsMgr.setEventCallback(null);
}
this._updating = false;
return;
}
/**重启游戏,并把缓存资源路径前置到搜索路径 */
if (needRestart) {
this._remoteVersion = this.getRemoteVersion();
console.log(TAG, `<updateCallback> remoteVersion: ${this._remoteVersion}`);
cc.sys.localStorage.setItem(GameLocalKey.CurrentHallVersions, this._remoteVersion);
if (this._hallAssetsMgr) {
this._hallAssetsMgr.setEventCallback(null);
}
let searchPaths = jsb.fileUtils.getSearchPaths();
let newPaths = this._hallAssetsMgr.getLocalManifest().getSearchPaths();
Array.prototype.unshift.apply(searchPaths, newPaths);
searchPaths = this.trimSearchPath(searchPaths);
console.log(TAG, `<updateCallback> searchPaths: ${JSON.stringify(searchPaths)}`);
cc.sys.localStorage.setItem(GameLocalKey.HotUpdateSearchPaths, JSON.stringify(searchPaths));
jsb.fileUtils.setSearchPaths(searchPaths);
cc.audioEngine.stopAll();
this.destroyFunc();
cc.game.restart();
}
}
测试调用类
onClickCheckUpdateBtnEvent() {
this._hallUpdateComp = this.getComponent(hallUpdateComp);
if (this._hallUpdateComp) {
this._hallUpdateComp.doCheckUpdate();
}
}