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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,458评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,030评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,879评论 0 358
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,278评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,296评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,019评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,633评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,541评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,068评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,181评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,318评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,991评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,670评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,183评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,302评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,655评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,327评论 2 358

推荐阅读更多精彩内容