CocosCreator系列——热更新超详细教程---2.2.1版本

CocosCreator系列——热更新超详细教程—2.2.1版本

新版本的热更新网上找了一些教程,大都大同小异,2.X新版本的更是少得可怜,最后运行的结果都是——运行不了……下载了官方案例,又经过两天的折腾,终于算是搞定了。
前期准备工作:首先看一下我另外一篇文章,先搭建一个简单的本地服务器.
1.新建一个checkUpdate场景,一个提示信息label,两个进度条和两个下载进度文字的显示label,内容如下:
CocosCreator系列——热更新超详细教程---2.2.1版本_第1张图片
然后编辑hotUpdate.js代码:

var UpdatePanel = require('../UI/UpdatePanel');

cc.Class({
    extends: cc.Component,

    properties: {
        panel: UpdatePanel,
        manifestUrl: {
            type: cc.Asset,
            default: null
        },
        updateUI: cc.Node,
        _updating: false,
        _canRetry: false,
        _storagePath: ''
    },

    onUpdateClick() {
        this.hotUpdate();
        this.updateUI.active = false;
    },

    onCancelClick() {
        cc.director.pause();
        cc.audioEngine.stopAll();
        if (cc.director.isPaused()) {
            cc.game.end();
        }
    },

    checkCb: function (event) {
        cc.log('Code: ' + event.getEventCode());
        let isUpdate = false; 
        switch (event.getEventCode()) {
            case jsb.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST:
                this.panel.info.string = "未找到本地清单文件,已跳过热更新.";
                break;
            case jsb.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST:
            case jsb.EventAssetsManager.ERROR_PARSE_MANIFEST:
                this.panel.info.string = "无法下载清单文件,已跳过热更新.";
                break;
            case jsb.EventAssetsManager.ALREADY_UP_TO_DATE:
                this.panel.info.string = "已经是最新远程版本的最新版本.";
                break;
            case jsb.EventAssetsManager.NEW_VERSION_FOUND:
                this.panel.info.string = '找到新版本,请尝试更新.';
                isUpdate = true ;
                this.panel.fileProgress.progress = 0;
                this.panel.byteProgress.progress = 0;
                break;
            default:
                return;
        }

        this._am.setEventCallback(null);
        this._checkListener = null;
        this._updating = false;

        if (isUpdate) { 
            this.updateUI.active = true;
        }
    },

    updateCb: function (event) {
        var needRestart = false;
        var failed = false;
        switch (event.getEventCode()) {
            case jsb.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST:
                this.panel.info.string = '未找到本地清单文件,已跳过热更新.';
                failed = true;
                break;
            case jsb.EventAssetsManager.UPDATE_PROGRESSION:
                this.panel.byteProgress.progress = event.getPercent();
                this.panel.fileProgress.progress = event.getPercentByFile();

                this.panel.fileLabel.string = event.getDownloadedFiles() + ' / ' + event.getTotalFiles();
                this.panel.byteLabel.string = event.getDownloadedBytes() + ' / ' + event.getTotalBytes();

                var msg = event.getMessage();
                if (msg) {
                    this.panel.info.string = 'Updated file: ' + msg;
                }
                break;
            case jsb.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST:
            case jsb.EventAssetsManager.ERROR_PARSE_MANIFEST:
                this.panel.info.string = '无法下载清单文件,已跳过热更新.';
                failed = true;
                break;
            case jsb.EventAssetsManager.ALREADY_UP_TO_DATE:
                this.panel.info.string = '已经是最新的远程版本.';
                failed = true;
                break;
            case jsb.EventAssetsManager.UPDATE_FINISHED:
                this.panel.info.string = '更新完成. ' + event.getMessage();
                needRestart = true;
                break;
            case jsb.EventAssetsManager.UPDATE_FAILED:
                this.panel.info.string = '更新失败. ' + event.getMessage();
                this._updating = false;
                this._canRetry = true;
                break;
            case jsb.EventAssetsManager.ERROR_UPDATING:
                this.panel.info.string = '资源更新错误: ' + event.getAssetId() + ', ' + event.getMessage();
                break;
            case jsb.EventAssetsManager.ERROR_DECOMPRESS:
                this.panel.info.string = event.getMessage();
                break;
            default:
                break;
        }

        if (failed) {
            this._am.setEventCallback(null);
            this._updateListener = null;
            this._updating = false;
        }

        if (needRestart) {
            this._am.setEventCallback(null);
            this._updateListener = null;
            var searchPaths = jsb.fileUtils.getSearchPaths();
            var newPaths = this._am.getLocalManifest().getSearchPaths();
            console.log(JSON.stringify(newPaths));
            Array.prototype.unshift.apply(searchPaths, newPaths);
            cc.sys.localStorage.setItem('HotUpdateSearchPaths', JSON.stringify(searchPaths));
            jsb.fileUtils.setSearchPaths(searchPaths);
            cc.audioEngine.stopAll();
            cc.game.restart();
        }
    },

    retry: function () {
        if (!this._updating && this._canRetry) {
            this._canRetry = false;

            this.panel.info.string = '重试失败 Assets...';
            this._am.downloadFailedAssets();
        }
    },

    checkUpdate: function () {
        if (this._updating) {
            this.panel.info.string = '检查或更新 ...';
            return;
        }
        if (this._am.getState() === jsb.AssetsManager.State.UNINITED) {
            // Resolve md5 url
            var url = this.manifestUrl.nativeUrl;
            if (cc.loader.md5Pipe) {
                url = cc.loader.md5Pipe.transformURL(url);
            }
            this._am.loadLocalManifest(url);
        }
        if (!this._am.getLocalManifest() || !this._am.getLocalManifest().isLoaded()) {
            this.panel.info.string = '未能加载本地清单 ...';
            return;
        }
        this._am.setEventCallback(this.checkCb.bind(this));

        this._am.checkUpdate();
        this._updating = true;
    },

    hotUpdate: function () {
        if (this._am && !this._updating) {
            this._am.setEventCallback(this.updateCb.bind(this));
            if (this._am.getState() === jsb.AssetsManager.State.UNINITED) {
                var url = this.manifestUrl.nativeUrl;
                if (cc.loader.md5Pipe) {
                    url = cc.loader.md5Pipe.transformURL(url);
                }
                this._am.loadLocalManifest(url);
            }

            this._failCount = 0;
            this._am.update();
            this._updating = true;
        }
    },

    // use this for initialization
    onLoad: function () {
        if (!cc.sys.isNative) {
            return;
        }
        this._storagePath = ((jsb.fileUtils ? jsb.fileUtils.getWritablePath() : '/') + 'remote-asset');
        cc.log('Storage path for remote asset : ' + this._storagePath);
        this.versionCompareHandle = function (versionA, versionB) {
            cc.log("JS Custom Version Compare: version A is " + versionA + ', version B is ' + versionB);
            var vA = versionA.split('.');
            var vB = versionB.split('.');
            for (var i = 0; i < vA.length; ++i) {
                var a = parseInt(vA[i]);
                var b = parseInt(vB[i] || 0);
                if (a === b) {
                    continue;
                } else {
                    return a - b;
                }
            }
            if (vB.length > vA.length) {
                return -1;
            } else {
                return 0;
            }
        };

        // Init with empty manifest url for testing custom manifest
        this._am = new jsb.AssetsManager('', this._storagePath, this.versionCompareHandle);

        var panel = this.panel;
        this._am.setVerifyCallback(function (path, asset) {
            var compressed = asset.compressed;
            var expectedMD5 = asset.md5;
            var relativePath = asset.path;
            var size = asset.size;
            if (compressed) {
                panel.info.string = "Verification passed : " + relativePath;
                return true;
            } else {
                panel.info.string = "Verification passed : " + relativePath + ' (' + expectedMD5 + ')';
                return true;
            }
        });

        this.panel.info.string = '已准备好热更新,请检查或直接更新.';

        if (cc.sys.os === cc.sys.OS_ANDROID) {
            this._am.setMaxConcurrentTask(2);
            this.panel.info.string = "最大并发任务数限制为2";
        }

        this.panel.fileProgress.progress = 0;
        this.panel.byteProgress.progress = 0;
        this.checkUpdate(); 
    },

    onDestroy: function () {
        if (this._updateListener) {
            this._am.setEventCallback(null);
            this._updateListener = null;
        }
    },
    onBrn() {
        cc.director.loadScene("test1");
    }
});

UpdatePanel代码:

cc.Class({
    extends: cc.Component,

    properties: {
        info: cc.Label,
        fileProgress: cc.ProgressBar,
        byteProgress: cc.ProgressBar,
        fileLabel: cc.Label,
        byteLabel: cc.Label,
    },

    // LIFE-CYCLE CALLBACKS:

    // onLoad () {},

    start() {

    },

    // update (dt) {},
});

3.绑定事件
CocosCreator系列——热更新超详细教程---2.2.1版本_第2张图片
4.下载manifest插件
CocosCreator系列——热更新超详细教程---2.2.1版本_第3张图片
5.保存构建项目不要编译
6.ctrl+u打开下载的热更新插件,并配置参数
CocosCreator系列——热更新超详细教程---2.2.1版本_第4张图片
7.然后点击生成,会在项目根目录下生成一个packVersion文件夹,然后解压
CocosCreator系列——热更新超详细教程---2.2.1版本_第5张图片
8.把解压出来的四个文件放到热更服务目录下
CocosCreator系列——热更新超详细教程---2.2.1版本_第6张图片
9.将两个manifest文件放入Cocos项目assets/resources/update目录下,并把project文件拖入右侧
CocosCreator系列——热更新超详细教程---2.2.1版本_第7张图片

10.再次构建项目,然后构建完成后打开main.js文件
CocosCreator系列——热更新超详细教程---2.2.1版本_第8张图片
11.在main.js文件第一行加入一下代码:

if(jsb){
    var hotUpdateSearchPaths = localStorage.getItem('HotUpdateSearchPaths');
        if (hotUpdateSearchPaths) {
            jsb.fileUtils.setSearchPaths(hotUpdateSearchPaths);
        }
}

12.然后编译,出包,安装到手机。
13.再次打开项目,新建场景和脚本
CocosCreator系列——热更新超详细教程---2.2.1版本_第9张图片
构建项目,不要编译,然后打开热更新插件
CocosCreator系列——热更新超详细教程---2.2.1版本_第10张图片
然后点击生成,把新的四个资源文件放到服务器更新目录下,这个时候在刷新一下服务器,确保资源上传的是已经更新过的。然后手机连接WiFi,确保处于同一个局域网下(可以用手机链接一下看看能不能登陆上去自己部署的服务器),如果能登陆,那么再次打开项目就可以正常更新了。
真的是不容易,做这个热更新整整搞了两天,查了好多资料,终于是搞定了,以前没做过也不知道流程,建议做这个功能之前,一定要先了解清楚热更原理和流程,然后再参考别人现有的资料来做,会事半功倍,要先学会走再学跑!!!
我的注释还有步骤已经很详细很详细了,如果还有哪里不懂的可以关注我一波,私信我教你哦~(●’◡’●)

你可能感兴趣的:(CocosCreator)