Cocos Creator app update the game content
1. Setup the Project
Create a New Cocos Creator Project:
Open Cocos Creator and create a new project.
Setup Project Structure: Organize your project files and ensure that all your assets, scripts, and resources are properly structured.
2. Enable Hot Update in Cocos Creator Cocos Creator uses a module called AssetsManager for handling hot updates.
Create a Hot Update Script: Create a new JavaScript or TypeScript script in your project and name it HotUpdate.js.
cc.Class({
extends: cc.Component,
properties: {
manifestUrl: {
type: cc.Asset,
default: null
},
updateUI: {
type: cc.Node,
default: null
},
},
onLoad() {
if (!cc.sys.isNative) {
return;
}
this._am = new jsb.AssetsManager(this.manifestUrl.nativeUrl, this.getWritablePath());
this._am.setVersionCompareHandle(this.versionCompareHandle);
this._am.setVerifyCallback(this.verifyCallback);
this.updateListener = new jsb.EventListenerAssetsManager(this._am, this.checkCb.bind(this));
cc.eventManager.addListener(this.updateListener, 1);
this.checkUpdate();
},
getWritablePath() {
return ((jsb.fileUtils ? jsb.fileUtils.getWritablePath() : '/') + 'blackjack-remote-asset');
},
versionCompareHandle(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]);
if (a === b) {
continue;
}
else {
return a - b;
}
}
if (vB.length > vA.length) {
return -1;
}
else {
return 0;
}
},
verifyCallback(path, asset) {
var compressed = asset.compressed;
var expectedMD5 = asset.md5;
var relativePath = asset.path;
var size = asset.size;
if (compressed) {
console.log("Verification passed: " + relativePath);
return true;
} else {
console.log("Verification passed: " + relativePath + ' (' + expectedMD5 + ')');
return true;
}
},
checkUpdate() {
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);
}
if (!this._am.getLocalManifest() || !this._am.getLocalManifest().isLoaded()) {
console.log("Failed to load local manifest ...");
return;
}
this._am.checkUpdate();
},
checkCb(event) {
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:
console.log("Already up to date with the latest remote version.");
break;
case jsb.EventAssetsManager.NEW_VERSION_FOUND:
console.log("New version found, please try to update.");
this._am.update();
break;
default:
return;
}
cc.eventManager.removeListener(this.updateListener);
this.updateListener = null;
},
updateCb(event) {
var needRestart = false;
var failed = false;
switch (event.getEventCode()) {
case jsb.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST:
case jsb.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST:
case jsb.EventAssetsManager.ERROR_PARSE_MANIFEST:
console.log("No local manifest file found, hot update skipped.");
failed = true;
break;
case jsb.EventAssetsManager.UPDATE_PROGRESSION:
console.log('Update progression: ' + event.getPercent() + '%');
break;
case jsb.EventAssetsManager.ALREADY_UP_TO_DATE:
console.log("Already up to date with the latest remote version.");
failed = true;
break;
case jsb.EventAssetsManager.UPDATE_FINISHED:
console.log('Update finished. ' + event.getMessage());
needRestart = true;
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;
}
if (needRestart) {
cc.audioEngine.stopAll();
cc.game.restart();
}
},
});
3. Create a Manifest File
The manifest file contains information about the version of your game and the resources to be updated.
Create a manifest file: Create a project.manifest file in your project directory.
{
"packageUrl": "http://yourserver.com/remote-assets/",
"remoteManifestUrl": "http://yourserver.com/remote-assets/project.manifest",
"remoteVersionUrl": "http://yourserver.com/remote-assets/version.manifest",
"version": "1.0.0",
"assets": {},
"searchPaths": []
}
Create a version manifest file: Create a version.manifest file in the same directory.
{
"packageUrl": "http://yourserver.com/remote-assets/",
"remoteManifestUrl": "http://yourserver.com/remote-assets/project.manifest",
"remoteVersionUrl": "http://yourserver.com/remote-assets/version.manifest",
"version": "1.0.0"
}
4. Upload Files to Server
Host the assets and manifest files on a web server:
Upload the project.manifest, version.manifest, and all the game assets to your server.
Update the manifest file:
Update the assets section in the manifest file with the paths and MD5 checksums of your assets.
5. Integrate Hot Update Script
Attach the Hot Update Script to a Node:
Attach the HotUpdate.js script to a node in your scene. Configure the Hot Update Component: Set the manifestUrl property in the Properties panel to point to your project.manifest file.
6. Testing the Hot Update
Build and Run the Project:
Build and run your project on a native platform (iOS/Android).
Simulate Updates:
Make changes to your assets or code, update the version in the manifest file, and upload the new files to the server. Restart the app to see the hot update process in action.
7. Handle Update Events
Customize the update process by handling different update events like UPDATE_PROGRESSION, UPDATE_FINISHED, and UPDATE_FAILED to provide feedback to users.
All rights reserved