热更新的使用:官方教程:
官网热更新教程
第一步:先生成配置文件:project.manifest和version.manifest,这两个文件的作用,官网有说明
第二步:创建loading脚本,继承BaseLoading,在属性面板,设置热更新的配置文件和热更新的弹窗
热更新属性面板配置
第三步:loading脚本中实现_fCheckUpdate方法,最后手动调用_fCheck函数,引擎自己会去对比远程和本地的版本文件
第四步:调用startHotUpate函数实现热更新,热更新结束后,游戏会重启,这样获取的就是服务器上最新的资源和脚本
updateCb这个函数中,如果版本是最新的,会进入jsb.EventAssetsManager.ALREADY_UP_TO_DATE:分支,直接读取游戏配置文件进入游戏
this._loadResCfgJson()updateCb这个函数的jsb.EventAssetsManager.UPDATE_PROGRESSION:分支,可以监听到当前下载更新的进度更新的下载进度的监听
event.getDownloadedBytes()当前下载文件的进度
event.getTotalBytes()下载文件的总大小
具体原理可以查看官方教程文档:热更新原理
这里解释下:这个指令
node version_generator.js -v 1.0.0 -u http://your-server-address/tutorial-hot-update/remote-assets/ -s native/package/ -d assets/
官方的解释是这样的:
-v 指定 Manifest 文件的主版本号。
-u 指定服务器远程包的地址,这个地址需要和最初发布版本中 Manifest 文件的远程包地址一致,否则无法检测到更新。
-s 本地原生打包版本的目录相对路径。
-d 保存 Manifest 文件的地址。
经过几代的变迁,现在一般的路径是:
-s 本地原生打包的版本:默认的构建版本路径:/build/jsb-link下
-d 就是你构建完成后,执行上面那条指令后生成最新的热更新配置文件,生成后的存放位置
所以现在一般是:
node version_generator.js -v 1.10.091 -u http://your-server-address/tutorial-hot-update/remote-assets/ -s build/jsb-link -d build/jsb-link/
version_generator.js 下载地址:version_generator.js
将生成出来的总的几个传到服务器即可
最后附上代码:
/**
* 开始检查更新--前往检测版本差异
*/
_fCheck () {
// Hot update is only available in Native build
if (! this._isNative()) {
return;
}
this._storagePath = ((jsb.fileUtils ? jsb.fileUtils.getWritablePath() : '/') + 'blackjack-remote-asset');
console.log('Storage path for remote asset : ' + this._storagePath);
// Setup your own version compare handler, versionA and B is versions in string
// if the return value greater than 0, versionA is greater than B,
// if the return value equals 0, versionA equals to B,
// if the return value smaller than 0, versionA is smaller than B.
this._versionCompareHandle = function (versionA, versionB) {
console.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);
if (! cc.sys.ENABLE_GC_FOR_NATIVE_OBJECTS) {
this._am.retain();
}
this._am.setVerifyCallback(function (path, asset) {
var compressed = asset.compressed;
var expectedMD5 = asset.md5;
var relativePath = asset.path;
var size = asset.size;
if (compressed) {
return true;
}
else {
return true;
}
});
if (cc.sys.os === cc.sys.OS_ANDROID) {
this._am.setMaxConcurrentTask(2);
}
this.checkUpdate();
},
updateCb (event) {
var needRestart = false;
var failed = false;
Com.info('updateCb Code : ' + event.getEventCode())
switch (event.getEventCode())
{
case jsb.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST:
console.log("No local manifest file found, hot update skipped.");
failed = true;
break;
case jsb.EventAssetsManager.UPDATE_PROGRESSION:
var msg = event.getMessage();
if (msg) {
console.log('Updated file: ' + msg);
}
// this._node_HotUpdate.setProgressLength(event.getDownloadedBytes(), event.getTotalBytes());
if (this['_hotUpdateProgress']) {
this['_hotUpdateProgress'](event.getDownloadedBytes(), event.getTotalBytes())
}
break;
case jsb.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST:
case jsb.EventAssetsManager.ERROR_PARSE_MANIFEST:
console.log("Fail to download manifest file, hot update skipped.");
failed = true;
break;
case jsb.EventAssetsManager.ALREADY_UP_TO_DATE:
failed = true;
Com.info('开始进入游戏1')
console.log("Already up to date with the latest remote version.");
//this._loadResCfgJson()
break;
case jsb.EventAssetsManager.UPDATE_FINISHED:
needRestart = true;
console.log('Update finished. ' + event.getMessage());
break;
case jsb.EventAssetsManager.UPDATE_FAILED:
console.log('Update failed. ' + event.getMessage());
break;
case jsb.EventAssetsManager.ERROR_UPDATING:
console.log('Asset update error: ' + event.getAssetId() + ', ' + event.getMessage());
break;
case jsb.EventAssetsManager.ERROR_DECOMPRESS:
console.log(event.getMessage());
break;
default:
break;
}
if (failed) {
cc.eventManager.removeListener(this._updateListener);
this._updateListener = null;
this._updating = false;
}
if (needRestart) {
cc.eventManager.removeListener(this._updateListener);
this._updateListener = null;
var searchPaths = jsb.fileUtils.getSearchPaths();
var newPaths = this._am.getLocalManifest().getSearchPaths();
console.log(JSON.stringify(newPaths));
Array.prototype.unshift(searchPaths, newPaths);
cc.sys.localStorage.setItem('HotUpdateSearchPaths', JSON.stringify(searchPaths));
jsb.fileUtils.setSearchPaths(searchPaths);
cc.audioEngine.stopAll();
cc.game.restart();
}
},
//检查更新
checkUpdate: function () {
if (this._am.getState() === jsb.AssetsManager.State.UNINITED) {
this._am.loadLocalManifest(this.manifestUrl)
// Resolve md5 url
/**********官方文档中的nativeUrl字段,在配置文件中是不存在的,导致会找不到本地的对比文件,坑******************* */
// var url = this.manifestUrl.nativeUrl;
// if (cc.loader.md5Pipe) {
// url = cc.loader.md5Pipe.transformURL(url);
// }
// this._am.loadLocalManifest(url);
/**********官方文档中的nativeUrl字段,在配置文件中是不存在的,导致会找不到本地的对比文件,坑******************* */
}
if (!this._am.getLocalManifest() || !this._am.getLocalManifest().isLoaded()) {
// this.panel.info.string = 'Failed to load local manifest ...';
return;
}
/***********这个函数已经弃用,坑**************/
// this._am.setEventCallback(this.checkCb.bind(this));
/***********这个函数已经弃用,坑**************/
//函数改成这个
this._checkListener = new jsb.EventListenerAssetsManager(this._am, this.checkCb.bind(this));
cc.eventManager.addListener(this._checkListener, 1);
this._am.checkUpdate();
this._updating = true;
},
/**
* 开始热更新--这里开始热更新
*/
startHotUpate: function () {
if (this._am && !this._updating) {
// this._am.setEventCallback(this.updateCb.bind(this));
// 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);
// }
this._updateListener = new jsb.EventListenerAssetsManager(this._am, this.updateCb.bind(this))
cc.eventManager.addListener(this._updateListener, 1)
if (this._am.getState() === jsb.AssetsManager.State.UNINITED) {
this._am.loadLocalManifest(this.manifestUrl)
}
this._failCount = 0;
this._am.update();
this._updating = true;
}
},
checkCb (event) {
console.log('checkCb Code: ' + event.getEventCode());
switch (event.getEventCode())
{
case jsb.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST:
console.log("No local manifest file found, hot update skipped.");
break;
case jsb.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST:
case jsb.EventAssetsManager.ERROR_PARSE_MANIFEST:
console.log("Fail to download manifest file, hot update skipped.");//备注处理
break;
case jsb.EventAssetsManager.ALREADY_UP_TO_DATE:
Com.info('开始进入游戏2')
console.log("Already up to date with the latest remote version.");
//this._loadResCfgJson()
break;
case jsb.EventAssetsManager.NEW_VERSION_FOUND:
//this.showUpdateTip();//这里显示更新的提示框
break;
default:
return;
}
cc.eventManager.removeListener(this._checkListener);
this._checkListener = null;
this._updating = false;
},
retry () {
if (!this._updating && this._canRetry) {
this._canRetry = false;
console.log("Retry failed Assets...");
this._am.downloadFailedAssets();
}
},
onDestroy: function () {
if (this._updateListener) {
this._am.setEventCallback(null);
this._updateListener = null;
}
}
更多教程,it菜鸟