当前位置: 首页 > news >正文

【cocos creator】热更新

一、介绍

试了官方的热更新功能,总结一下
主要用于安卓包热更新

参考:

Cocos Creator 2.2.2 热更新简易教程
基于cocos creator2.4.x的热更笔记

二、使用软件
1、cocos creator v2.4.10

2、creator热更新插件:热更新manifest生成工具(creator应用商店下载)
cocos提供的脚本也可以用,但这个集成好了,更便捷
在这里插入图片描述

3、静态资源服务器(用的win+tomcat)
tomcat下载安装

4、模拟器

5、Android打包环境

三、配置热更新

1、首先确保项目可以正常构建出apk,进行一次构建
2、商城下载插件,安装好
在这里插入图片描述
3、配置好地址,只支持一个固定的地址,对应服务器存放热更新文件的文件夹
在这里插入图片描述
在这里插入图片描述
4、点击生成热更新包,再点击导入manifest

2.4.10控制台会提示xx已弃用,建议使用xx,按照提示全局搜索替换即可
在这里插入图片描述

5、把下面的脚本放在加载界面

manifest url绑定上一步导入的version,默认在assets下面
在这里插入图片描述

在这里插入图片描述


const { ccclass, property } = cc._decorator;@ccclass
export default class HotUpdate extends cc.Component {@property(cc.Node) progressNode: cc.Node = null;@property(cc.Label) alartLbl: cc.Label = null;@property(cc.Asset) manifestUrl: cc.Asset = null;  // 以资源的形式,绑定初始的manifestprivate _am: jsb.AssetsManager; // 热更的对象private _storagePath: string = '';private _hotPath: string = 'HotUpdateSearchPaths'private _progress: number = 0;private _downFailList: Map<string, number> = new Map();protected start(): void {this.alartLbl.string = ""this._showProgress(0);this.alartLbl.string = '';this._init();}private _init() {console.log("hotUpdate检测更新", cc.sys.os);if (cc.sys.os != cc.sys.OS_ANDROID && cc.sys.os != cc.sys.OS_IOS) {// 非原生平台不处理this._enterGame();return;}this.alartLbl.string = "检测更新..."this._storagePath = ((jsb.fileUtils ? jsb.fileUtils.getWritablePath() : '/') + this._hotPath);// 创建一个热更对象,提供一个本地资源路径,用来存放远程下载的资源。一个版本比较方法,用来判断是否需要更新this._am = new jsb.AssetsManager('', this._storagePath, this._versionCompareHandle);// 设置MD5 校验回调,这里一般用来比对文件是否正常// 如果这个方法返回true表示正常, 返回false的会触发文件下载失败,失败时会抛出错误事件ERROR_UPDATING,后面还会提到this._am.setVerifyCallback(function (filePath, asset) {// When asset is compressed, we don't need to check its md5, because zip file have been deleted.let compressed = asset.compressed;// Retrieve the correct md5 value.let expectedMD5 = asset.md5;// asset.path is relative path and path is absolute.let relativePath = asset.path;// The size of asset file, but this value could be absent.let size = asset.size;if (compressed) {return true;}else {// let expectedMD5 = asset.md5; // 远程project.manifest文件下资源对应的MD5// let resMD5: string = calculateMD5(filePath);  // filePath是文件下载到本地的路径,需要自行提供方法来计算文件的MD5// return resMD5 == expectedMD5;return true;}});if (cc.sys.os === cc.sys.OS_ANDROID) {// Some Android device may slow down the download process when concurrent tasks is too much.// The value may not be accurate, please do more test and find what's most suitable for your game.// this._am.setMaxConcurrentTask(2);}this._progress = 0;//检测更新this._checkUpdate();}/*** 版本对比,返回值小于0则需要更新* @param versionA 当前游戏内版本  本地* @param versionB 需要更新的版本  服务器* @returns */_versionCompareHandle(versionA: string, versionB: string) {console.log("JS Custom Version Compare: version A is " + versionA + ', version B is ' + versionB);let vA = versionA.split('.');let vB = versionB.split('.');for (let i = 0; i < vA.length; ++i) {let a = parseInt(vA[i]);let b = parseInt(vB[i] || '0');if (a === b) {continue;} else {return a - b;}}if (vB.length > vA.length) {return -1;} else {return 0;}}private async _checkUpdate() {// 判断当前热更的状态,没有初始化才加载本地Manifest,加载完成后状态会改变if (this._am.getState() === jsb.AssetsManager.State.UNINITED) {let url = this.manifestUrl.nativeUrl;this._am.loadLocalManifest(url); // 加载本地manifest}if (!this._am.getLocalManifest() || !this._am.getLocalManifest().isLoaded()) {console.error('Failed to load local manifest ...');return;}this._am.setEventCallback(this._checkCb.bind(this));this._am.checkUpdate();}private _checkCb(event: jsb.EventAssetsManager) {switch (event.getEventCode()) {case jsb.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST:case jsb.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST:case jsb.EventAssetsManager.ERROR_PARSE_MANIFEST:// manifest文件相关的错误,这里可以去做一些错误相关的处理console.error('加载manifest文件失败', event.getEventCode())break;case jsb.EventAssetsManager.ALREADY_UP_TO_DATE:// 当前版本已经是最新版本cc.log('hotUpdate Already up to date with the latest remote version.');this._enterGame();break;case jsb.EventAssetsManager.NEW_VERSION_FOUND:// 找到新的版本console.log(`hotUpdate New version found, please try to update. (${this._am.getTotalBytes()})`);cc.log(`hotUpdate getDownloadedBytes${this._am.getDownloadedBytes()}`);cc.log(`hotUpdate getTotalBytes${this._am.getTotalBytes()}`);this._am.setEventCallback(null);this._downLoadAlart();break;default:return;}}private _downLoadAlart() {this.alartLbl.string = "开始更新..."// 检测到有新版本则直接更新,也可以改成点击按钮再更新,这一步可以根据自己的需求来处理this._hotUpdate();}// 开始更新private _hotUpdate() {console.log('hotUpdate开始更新')this._am.setEventCallback(this._updateCb.bind(this));this._am.update();}private _updateCb(event: jsb.EventAssetsManager) {var needRestart = false, file = null;console.log('hotUpdate _updateCb', event.getEventCode())this.alartLbl.string = "更新中..."switch (event.getEventCode()) {case jsb.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST:case jsb.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST:case jsb.EventAssetsManager.ERROR_PARSE_MANIFEST:// manifest文件相关的错误,这里可以去做一些错误相关的处理break;case jsb.EventAssetsManager.ERROR_UPDATING:file = event.getAssetId();// 文件更新出错,这里有可能是验证方法没有通过,也有可能是文件下载失败等等this._updateFailList(file, false);break;case jsb.EventAssetsManager.ERROR_DECOMPRESS:// 文件解压缩失败break;case jsb.EventAssetsManager.UPDATE_FAILED:cc.error(`Fail to Update -> ${event.getMessage()}`);let failed = false;this._downFailList.forEach((count) => {if (count > 3) {failed = true;}});if (failed) {// 超过3次失败,显示下载失败// this._showUpdateFalid();} else {cc.log(`HotUpdate failed...Restart Update`);this._am.downloadFailedAssets();  // 重新下载失败的文件}break;case jsb.EventAssetsManager.UPDATE_PROGRESSION:// 这里处理正常下载进度显示if (event.getPercent()) {let downloadBytes = event.getDownloadedBytes() || 0;let totalBytes = event.getTotalBytes() || 0;this._progress = Math.floor(downloadBytes / totalBytes * 100);if (this._progress <= 0) return;this._showProgress(this._progress);let unit = 1048576;/* 1MB = 1,024 KB = 1,048,576 Bytes */let downloadedMB = (downloadBytes / unit).toFixed(2) + 'MB';let totalMB = (totalBytes / unit).toFixed(2) + 'MB';this.alartLbl.string = `下载资源: ${this._progress}% (${downloadedMB}/${totalMB})`;cc.log('hotUpdate downloadBytes=>', this._progress, downloadedMB, totalMB);}break;case jsb.EventAssetsManager.ALREADY_UP_TO_DATE:// 已经是最新版本cc.log('hotUpdate Already up to date with the latest remote version...');this._enterGame();break;case jsb.EventAssetsManager.UPDATE_FINISHED:cc.log(`hotUpdate Update finished. ${event.getMessage()}`);// 更新完成,这里去做重启needRestart = true;break;case jsb.EventAssetsManager.ASSET_UPDATED:// 每次资源下载成功会回调到这里,可以根据需求做一些处理cc.log('hotUpdate Updated file: ' + event.getAssetId() + ' ' + event.getMessage());file = event.getAssetId();this._updateFailList(file, true);break;default:break;}if (needRestart) {this._am.setEventCallback(null);var newPaths = this._storagePath;// 将当前路径写入到本地,持久化数据以便下次游戏启动的时候能拿到cc.sys.localStorage.setItem(this._hotPath, JSON.stringify([newPaths]));this.alartLbl.string = "更新完成"cc.game.restart();}}private _updateFailList(file: string, success: boolean) {if (success) {this._downFailList.delete(file);cc.log('hotUpdate 更新成功', file);} else {if (this._downFailList.get(file)) {let count = this._downFailList.get(file);this._downFailList.set(file, count + 1);cc.log(`hotUpdate ${file} download fail count ${count + 1}`);} else {this._downFailList.set(file, 1);cc.log(`hotUpdate ${file} download fail count 1`);}}}private _showProgress(percent: number) {percent > 100 && (percent = 100);let progress = cc.winSize.width * percent / 100;this.progressNode.width = progress;}private _enterGame() {console.log("hotUpdate 加载游戏");//TODO  加载游戏场景cc.director.loadScene("game");}
}

本来还要在build\jsb-default\main.js开头添加热更新代码,插件集成好了,省略这一步

6、点击编译导出apk,安装在手机上
原始含有热更新功能的包就打包好了

7、修改一部分内容,再次构建(只需要构建)
然后在热更新工具把版本号增加一位,点击生成热更包

将导出的压缩包放到服务器解压
在这里插入图片描述
手机上打开之前安装的包,就会自动更新成最新版本

相关文章:

【cocos creator】热更新

一、介绍 试了官方的热更新功能&#xff0c;总结一下 主要用于安卓包热更新 参考&#xff1a; Cocos Creator 2.2.2 热更新简易教程 基于cocos creator2.4.x的热更笔记 二、使用软件 1、cocos creator v2.4.10 2、creator热更新插件&#xff1a;热更新manifest生成工具&…...

黑金风格人像静物户外旅拍Lr调色教程,手机滤镜PS+Lightroom预设下载!

调色教程 针对人像、静物以及户外旅拍照片&#xff0c;运用 Lightroom 软件进行风格化调色工作。旨在通过软件中的多种工具&#xff0c;如基本参数调整、HSL&#xff08;色相、饱和度、明亮度&#xff09;调整、曲线工具等改变照片原本的色彩、明度、对比度等属性&#xff0c;将…...

部署vue+django项目(初版)

1.准备 vscode 插件Remote SSH&#xff0c;连接远程&#xff0c;打开远程中home文件夹。 镜像和容器的一些常用命令 docker images docker ps 查看所有正在运行的容器 docker ps -a docker rmi -f tk-django-app 删除镜像 docker rm xxx 删除容器 docker start xxxx …...

Redis7系列:设置开机自启

前面的文章讲了Redis和Redis Stack的安装&#xff0c;随着服务器的重启&#xff0c;导致Redis 客户端无法连接。原来的是Redis没有配置开机自启。此文记录一下如何配置开机自启。 1、修改配置文件 前面的Redis和Redis Stack的安装的文章中已经讲了redis.config的配置&#xf…...

HarmonyOS学习第18天:多媒体功能全解析

一、开篇引入 在当今数字化时代&#xff0c;多媒体已经深度融入我们的日常生活。无论是在工作中通过视频会议进行沟通协作&#xff0c;还是在学习时借助在线课程的音频讲解加深理解&#xff0c;亦或是在休闲时光用手机播放音乐放松身心、观看视频打发时间&#xff0c;多媒体功…...

在rocklinux里面批量部署安装rocklinx9

部署三台Rockylinux9服务器 实验要求 1. 自动安装ubuntu server20以上版本 2. 自动部署三台Rockylinux9服务器&#xff0c;最小化安装&#xff0c;安装基础包&#xff0c;并设定国内源&#xff0c;设静态IP 实验步骤 安装软件 # yum源必须有epel源 # dnf install -y epel-re…...

Manus:成为AI Agent领域的标杆

一、引言 官网&#xff1a;Manus 随着人工智能技术的飞速发展&#xff0c;AI Agent&#xff08;智能体&#xff09;作为人工智能领域的重要分支&#xff0c;正逐渐从概念走向现实&#xff0c;并在各行各业展现出巨大的应用潜力。在众多AI Agent产品中&#xff0c;Manus以其独…...

【Java开发指南 | 第三十四篇】IDEA没有Java Enterprise——解决方法

读者可订阅专栏&#xff1a;Java开发指南 |【CSDN秋说】 文章目录 1、新建Java项目2、单击项目名&#xff0c;并连续按两次shift键3、在搜索栏搜索"添加框架支持"4、勾选Web应用程序5、最终界面6、添加Tomcat 1、新建Java项目 2、单击项目名&#xff0c;并连续按两次…...

WinForm模态与非模态窗体

1、模态窗体 1&#xff09;定义&#xff1a; 模态窗体是指当窗体显示时&#xff0c;用户必须先关闭该窗体&#xff0c;才能继续与应用程序的其他部分进行交互。 2&#xff09;特点&#xff1a; 窗体以模态方式显示时&#xff0c;会阻塞主窗体的操作。用户必须处理完模态窗体上…...

静态时序分析:SDC约束命令set_ideal_network详解

相关阅读 静态时序分析https://blog.csdn.net/weixin_45791458/category_12567571.html?spm1001.2014.3001.5482 set_ideal_network命令可以将当前设计中的一组端口或引脚标记为理想网络源&#xff08;设置端口或引脚对象的ideal_network_source属性为true&#xff09;&#…...

【学习方法】技术开发者的提问智慧:如何高效获得解答?

技术开发者的提问智慧&#xff1a;如何高效获得解答&#xff1f; 在技术开发过程中&#xff0c;每个人都会遇到无法解决的问题。此时&#xff0c;我们通常会向团队、社区或论坛求助。然而&#xff0c;为什么有些人的问题能迅速得到解答&#xff0c;而有些人的问题却石沉大海&a…...

C++:入门详解(关于C与C++基本差别)

目录 一.C的第一个程序 二.命名空间&#xff08;namespace&#xff09; 1.命名空间的定义与使用&#xff1a; &#xff08;1&#xff09;命名空间里可以定义变量&#xff0c;函数&#xff0c;结构体等多种类型 &#xff08;2&#xff09;命名空间调用&#xff08;&#xf…...

服务器上的nginx因漏洞扫描需要升级

前言 最近客户联系说nginx存在安全漏洞 F5 Nginx 安全漏洞(CVE-2024-7347) F5Nginx是美国F5公司的一款轻量级Web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器&#xff0c;在BSD-like协议下发行。F5 Nginx存在安全漏洞&#xff0c;该漏洞源于可能允许攻击者使用特制的…...

1688商品列表商品详情API接口全面解析

1688作为中国领先的B2B电子商务平台&#xff0c;汇聚了海量的商品资源&#xff0c;为商家和采购商提供了丰富的交易机会。为了更方便地获取和利用这些商品信息&#xff0c;1688平台提供了商品列表API接口&#xff0c;允许第三方开发者通过编程方式获取平台上的商品列表数据。本…...

【爬虫】开篇词

一、网络爬虫概述 二、网络爬虫的应用场景 三、爬虫的痛点 四、需要掌握哪些技术&#xff1f; 在这个信息爆炸的时代&#xff0c;如何高效地获取和处理海量数据成为一项核心技能。无论是数据分析、商业情报、学术研究&#xff0c;还是人工智能训练&#xff0c;网络爬虫&…...

如何在SpringBoot中灵活使用异步事件?

在现代的应用开发中&#xff0c;事件驱动的架构越来越受到欢迎。当我们在使用SpringBoot时&#xff0c;了解如何实现异步事件变得尤为重要。通过事件机制&#xff0c;我们能够在系统中实现松耦合的组件&#xff0c;让不同模块之间能够有效沟通&#xff0c;而无需直接依赖。本文…...

S19文件格式详解:汽车ECU软件升级中的核心镜像格式

文章目录 引言一、S19文件格式的起源与概述二、S19文件的核心结构三、S19在汽车ECU升级中的应用场景四、S19与其他格式的对比五、S19文件实例解析六、工具链支持与安全考量七、未来趋势与挑战结语引言 在汽车电子控制单元(ECU)的软件升级过程中,S19文件(也称为Motorola S-…...

git安装(windows)+vscode配置

安装git for windows在使用 Git 之前&#xff0c;建议设置全局的用户名称和电子邮件地址&#xff0c;这样每次提交代码时就可以自动关联您的身份信息。设置一次后&#xff0c;您无需每次都输入这些信息&#xff0c;Git 将自动使用您配置的全局用户信息。如果需要针对特定项目使…...

Python性能优化面试题及参考答案

目录 解释字典与列表在查找操作中的时间复杂度差异,如何利用哈希表特性提升性能? 为什么在只读场景下使用元组(tuple)比列表(list)更高效? 如何用 collections.deque 优化频繁的队列插入 / 删除操作? defaultdict 相比普通字典在哪些场景下能减少冗余代码并提升效率…...

【十四】Golang 接口

&#x1f4a2;欢迎来到张胤尘的开源技术站 &#x1f4a5;开源如江河&#xff0c;汇聚众志成。代码似星辰&#xff0c;照亮行征程。开源精神长&#xff0c;传承永不忘。携手共前行&#xff0c;未来更辉煌&#x1f4a5; 文章目录 接口接口定义接口初始化接口嵌套空接口存储任意类…...

ngx_openssl_create_conf

ngx_openssl_create_conf 声明在 src\event\ngx_event_openssl.c static void *ngx_openssl_create_conf(ngx_cycle_t *cycle); 定义在 src\event\ngx_event_openssl.c static void * ngx_openssl_create_conf(ngx_cycle_t *cycle) {ngx_openssl_conf_t *oscf;oscf ngx_…...

54-WLAN 无线局域网配置方案-三层

一、网络拓扑说明 本 WLAN 网络由交换机&#xff08;LSW1&#xff09;、无线控制器&#xff08;AC1&#xff09;、无线接入点&#xff08;AP1\2&#xff09;以及无线客户端&#xff08;STA1&#xff09;组成。 用途VLANAC100AP200业务300 二、设备配置 二、设备配置 &#x…...

JVM 类加载原理之双亲委派机制(JDK8版本)

对 Java 程序的运行过程而言&#xff0c;类的加载依赖类加载器完成&#xff0c;而在 Java 默认的类加载器又分为启动类加载器、扩展类加载器和应用程序类加载器三种&#xff0c;但是一个类通常仅仅需要被加载一次即可&#xff0c;双亲委派机制即规定各个类该被何种类加载器加载…...

Mysql快速学习——《一》: Mysql的基础架构

了解mysql的基础架构, 理解大概的实现思想, 更有利与我们知之所以然, 是我们学习mysql起来思路更清晰, 效率更高. 思维导图: mysql 基础架构 mysql基础架构.png 1. 连接器 Mysql作为服务器&#xff0c;一个客户端的Sql连接过来就需要分配一个线程进行处理&#xff0c;这个线程…...

【华为OD机试真题29.9¥】(E卷,100分) - 运维日志排序(Java Python JS C++ C )

最新华为OD机试 题目描述 [运维工程师]采集到某产品线网运行一天产生的日志n条&#xff0c;现需根据日志时间先后顺序对日志进行排序&#xff0c;日志时间格式为H:M:S.N。 H表示小时(0~23)M表示分钟(0~59)S表示秒(0~59)N表示毫秒(0~999) 时间可能并没有补全&#xff0c;也就…...

rust编程实战:实现3d粒子渲染wasm

源码 纯js实现 fps&#xff1a; wasm实现 通过对比可以看出来 wasm 实现的计算比纯js刷新相对稳定。...

本地部署Navidrome个人云音乐平台随时随地畅听本地音乐文件

文章目录 前言1. 安装Docker2. 创建并启动Navidrome容器3. 公网远程访问本地Navidrome3.1 内网穿透工具安装3.2 创建远程连接公网地址3.3 使用固定公网地址远程访问 前言 今天我要给大家安利一个超酷的私有化音乐神器——Navidrome&#xff01;它不仅让你随时随地畅享本地音乐…...

Unity自定义区域UI滑动事件

自定义区域UI滑动事件 介绍制作1.创建一个Image2.创建脚本 总结 介绍 一提到滑动事件联想到有太多的插件了比如EastTouchBundle&#xff0c;今天想单纯通过UI去做一个滑动事件而不是基于Box2d或者Box去做滑动事件。 制作 1.创建一个Image 2.创建脚本 using UnityEngine; us…...

Redis7——进阶篇(五)

前言&#xff1a;此篇文章系本人学习过程中记录下来的笔记&#xff0c;里面难免会有不少欠缺的地方&#xff0c;诚心期待大家多多给予指教。 基础篇&#xff1a; Redis&#xff08;一&#xff09;Redis&#xff08;二&#xff09;Redis&#xff08;三&#xff09;Redis&#x…...

时序和延时

1、延迟模型的类型 verilog有三种类型的延迟模型&#xff1a;分布延迟 、 集总延迟 、 路径延迟&#xff08;pin to pin&#xff09; 1.1、 分布延迟 分布延迟是在每个独立元件的基础上进行定义的。 module M(output wire out ,input wire a …...