CocosCreator热更新

环境说明:

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();
    }
}

详细实现代码工程逻辑请注意wx恭重耗GFanStudio回复 "热更新" 即可获得项目工程下载地址;具体教学视频请看B站GFanStudio

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容