Unity——热更新浅析

热更新的思想从本质上来讲,要考虑一些问题。例如,一个完整的游戏最多可以有多大比例的资源通过网络加载?能否让尽可能多的资源通过网络加载?

通过网络加载有很多好处,不仅可以极大减小安装包的体积,而且有助于游戏的推广传播。更重要的是,以后游戏更新都不需要重新安装,只要有网络,打开游戏后自动加载新版本的资源就可以了。

那么哪些资源需要通过网络加载呢?首先,理论上几乎全部资源都可以通过网络加载;其次,Unity脚本本身不支持动态加载。针对这两点,前辈们想出了各种解决方案。

1.过渡场景

最容易想到的是,要想减小安装包体积,,应该在游戏中做一个最简单、最基本的过渡场景。过度场景本身需要的素材非常少(如只有一个加载进度条),其作用也只有一个——联网下载所有必要的资源包,等下载完成后再切换场景,正式启动游戏。如果采用这种设计,游戏的安装包只需要包含Unity引擎本身的资源、加载程序的资源和过渡场景的资源就足够了,从而安装包的容量可以做到非常小。

2.脚本的动态加载

举例理解脚本的动态加载

当涉及到脚本动态加载时,一个常见的比方是插件系统。

想象你正在开发一个图像编辑应用程序,用户可以选择不同的特效来编辑图片。而这些特效(或者称之为插件)可以以脚本的形式存在,并且可以在应用程序运行时动态加载和使用,而不需要在编译时将它们直接包含在应用程序中。

在这个比方中,应用程序就好比一个宿主系统,而特效脚本就是插件。通过脚本动态加载,你的应用程序可以根据用户的选择或动态配置在运行时加载特定的特效脚本,并将它们与图像进行交互以实现不同的编辑效果。

这种动态加载的插件系统允许你无需重新编译整个应用程序,就能够灵活地添加、删除或更新特效功能。用户可以根据需求自定义和扩展应用的功能,而不需要修改应用程序本身。

脚本资源最好也能通过网络加载更新。如果脚本不能更新,就只能更新美术资源和数据文件,而绝大部分游戏逻辑都无法改动,旧版本中的程序bug也无法修复。

脚本动态加载设计动态编译和执行的问题,属于很深入的技术问题。现代脚本动态加载的思路分为以下两大类。

第一类思路

将脚本编译成为动态链接库(DLL),然后把DLL当作资源打入资产包。使用脚本时,利用C#的反射机制,让DLL中的程序动态执行。

这种思路的优点是不需要改变原本的脚本编辑方法,仅仅在打包和加载时需要做一些额外的处理。也就是说,对开发者几乎不会带来额外的负担。但它也有着致命的缺点,在iOS平台上,出于安全考虑,不允许利用反射加载网络代码,因此这种做法在iOS等安全性要求较高的操作系统中无法使用。

使用反射加载网络代码可能存在安全风险,主要有以下几个原因:

1. 安全漏洞:通过网络加载的代码可能包含恶意代码或存在安全漏洞。这些代码可能会执行未经授权的操作,访问敏感信息,破坏系统稳定性,甚至攻击其他计算机或网络资源。

2. 无验证:反射提供了动态加载类型的能力,但它并没有内置的验证机制来验证这些类型的来源和完整性。因此,如果不仔细核实加载的代码的来源和内容,可能会导致不受信任的代码被加载和执行。

3. 代码注入:通过反射加载的代码可能会以注入的方式执行,这意味着它们与应用程序的其他部分的关系可能不明确或不可预测。这种情况下,代码可能会以无控制的方式访问和修改应用程序的内部状态,导致安全问题和不稳定性。

4. 权限提升:加载的代码可能尝试在执行时提升权限,获取系统管理员权限或执行特权操作,这可能会导致安全漏洞和未授权的访问。

 第二类思路

换一种全新的脚本框架,甚至可以换一种脚本开发语言。现在流行的热更新框架中,采用Lua作为开发语言比较常见。另外,也有采用C#语言的热更新框架,好处是不需要学习和使用另一种新的编程语言。

这种思路是在运行的环境中创建一个新的虚拟机,由虚拟机负责热更新脚本的运行。由于这些脚本只能调用有限的程序接口,而不会拥有过多权限,因此是相对安全的。

3.版本资源列表

在热更新技术中,有一个技术值得学习——版本资源列表。

需要版本资源列表的原因是,每次版本更新都需要对本地资源和远程服务器的资源进行版本对比。而且,如果用户的本地资源有一部分是新的,一部分是旧的,也需要某种机制保证快速、准确地更新旧的资源。

版本更新首先要以版本号作为基础。客户端有一个版本号,如1.0版,如果发现服务器端版本号是1.1版,则客户端就要下载1.1版的资源到本地。最简单的思路是,在服务器上存放一个从1.0到1.1版有变化的文件列表,客户根据该列表逐个更新资源即可,更新完成后版本号变为1.1。

这种思路可以达到效果,但不够灵活。更好的思路如下:

  1. 服务器端的每一个资源文件都计算一次MD5码,并将结果保存在资源列表里。
  2. 本地的每一个文件也要计算一次MD5码,为避免重复计算,可以计算一次后就保存在本地的列表文件中。
  3. 升级版本是,对比服务器端每个文件的MD5码和本地文件的MD5码,只下载MD5码不一致的文件
  4. 下载完成后可以重新计算MD5码,这样可以顺便检验在下载过程中数据传输是否出错
  5. 确保资源一致以后可以修改本地版本号,避免重复检查

 MD5码

MD5码是一种数据加密算法,它会便历文件中的所有数据,并将所有的数据以一种特殊算法合并,形成一个128比特(16)字节的数字。

相同数据计算出的MD5码也相同,如果文件中有任何一个比特变化,则生成的MD5码都会完全不同。现实中随意修改一个文件,但MD5码不变的概率接近0.这里借用的正式MD5码的这一性质。

虽然MD5码是一种加密算法,但其碰撞算法现已被破解,因此不再作为加密算法使用。但由于其具有算法简单、计算快的优点,因此作为文件一致性比较算法非常合适。


本文从思路上讲解了热更新这一技术产生的原因及其设计思想,可以看出热更新是以动态资源管理技术为基础的,也包括其他编程技术。热更新技术包含很多细节,因此市面上出现了多种功能齐全的热更新框架。

这些框架主要有以下功能:

  1. 提供执行热更新代码的虚拟机环境
  2. 把引擎提供的类型、方法和属性导出,让开发者可以在热更新代码中访问引擎功能
  3. 将开发者编写的Unity脚本接口导出,让热更新代码可以调用C#中的类型、方法和属性
  4. 提供一些方法,让Unity脚本可以使用热更新代码中的类型、函数和属性,大同两套代码之间的桥梁

一般来说,由于运行原理不同,动态加载的代码的执行效率会低于原生脚本。如果确实发现因动态脚本代码发生性能热点,可以将运算压力较大的部分用原生脚本编写,并封装成函数,然后让动态加载的代码调用该函数

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/62489.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SPSS教程:如何绘制带误差的折线图

SPSS教程:如何绘制带误差的折线图 1、问题与数据 研究者想研究45-65岁健康男性中,静坐时长和血胆固醇水平的关系,故招募100名研究对象询问其每天静坐时长(time),并检测其血液中胆固醇水平(cho…

Spring三级缓存解决循环依赖

Spring三级缓存解决循环依赖 一 Spring bean对象的生命周期 二 三级缓存解决循环依赖 实现原理解析 spring利用singletonObjects, earlySingletonObjects, singletonFactories三级缓存去解决的,所说的缓存其实也就是三个Map 先实例化的bean会通过ObjectFactory半…

什么是同源策略(same-origin policy)?它对AJAX有什么影响?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 同源策略(Same-Origin Policy)与 AJAX 影响⭐ 同源策略的限制⭐ AJAX 请求受同源策略影响⭐ 跨域资源共享(CORS)⭐ 写在最后 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 记…

Redo Log工作原理

数据库如何持久化数据? 数据库一般都需要硬盘来进行数据持久化 ,数据库在持续提供对外服务的过程会不断的进行写入操作(增、删、改),为了保证每次成功的写入都能落盘,就需要每次进行写入操作都调用fsync操…

汽车服务门店小程序模板制作指南

在数字化时代,一个小程序的力量不可忽视。它不仅是展示品牌形象和提供用户服务的重要工具,更是扩大客户群体和提高营收的关键手段。对于汽车服务门店来说,拥有一个精美且功能齐全的小程序,更将成为你在竞争激烈的市场中的重要武器…

Docker中容器的随机命名方式

使用 docker 创建容器时,如果没有用 --name 指定,docker 会为用户选择一个名称, 格式是两个带有下划线的单词,如xxx_yyyy 其相关的实现在此处 pkg/namesgenerator/names-generator.go[1] 源码中有两个数组,第一个是一个…

MySql Delete 使用及优化

一、概述 DELETE是一个DML语句,用于从表中删除行。 DELETE语句可以从with子句开始,以定义DELETE中可访问的公用表表达式。 单表语法 DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM tbl_name [[AS] tbl_alias][PARTITION (partition_name [, partition…

【Git游戏】远程分支

origin/<branch> 远程分支在本地以 origin/<branch>格式存在&#xff0c;他指向上次和远程分支通过时的记录 git checkout origin/<branch> 会出现HEAD分离的情况 与远程通讯 git fetch —— 从远端获取数据&#xff08;实际上将本地仓库中的远程分支更新…

mysql 内置函数

目录 日期函数 current_date current_time current_timestamp date now date_add date_sub datediff 字符串函数 charset concat instr ucase lcase left length replace strcmp substring ltrim/rtrim/trim ltrim rtrim trim 数学函数 abs bin hex …

ES线程池设置

一文搞懂ES中的线程池 - 知乎 ES线程池设置-阿里云开发者社区 文章目录 一、简介 二、线程池类型 2.1、fixed 2.2、scaling 2.3、direct 2.4、fixed_auto_queue_size 三、处理器设置 四、查看线程池 4.1、cat thread pool 4.2、nodes info 4.3、nodes stats 4.4、no…

前端网络相关的面试题

get和post经过几次tcp连接? HTTP的GET和POST请求都是基于TCP协议的&#xff0c;因此在发送请求之前都需要建立TCP连接。TCP连接的建立通常被称为三次握手&#xff08;Three-way Handshake&#xff09;。 第一次握手&#xff1a;客户端发送一个SYN包&#xff08;同步序列编号…

【python爬虫】8.温故而知新

文章目录 前言回顾前路代码实现体验代码功能拆解获取数据解析提取数据存储数据 程序实现与总结 前言 Hello又见面了&#xff01;上一关我们学习了爬虫数据的存储&#xff0c;并成功将QQ音乐周杰伦歌曲信息的数据存储进了csv文件和excel文件。 学到这里&#xff0c;说明你已经…

nvm集合node版本,解决新版本jeecgboot3.5.3前端启动失败问题

jeecgboot前端3.5.3页面如下 使用之前的pnpm启动会报错&#xff0c;pnpm是node进行安装的&#xff0c;查询后发现&#xff0c;vue3版本的页面至少需要node16版本&#xff0c;我之前的版本只有15.5&#xff0c;适用于vue2 那么我将先前的node15.5版本删除&#xff0c;然后安装…

【Hadoop】DataNode 详解

&#x1f341; 博主 "开着拖拉机回家"带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——&#x1f390;开着拖拉机回家_Linux,Java基础学习,大数据运维-CSDN博客 &#x1f390;✨&#x1f341; &#x1fa81;&#x1f341; 希望本文能够给您带来一定的…

Redis——》实现分布式锁

推荐链接&#xff1a; 总结——》【Java】 总结——》【Mysql】 总结——》【Redis】 总结——》【Kafka】 总结——》【Spring】 总结——》【SpringBoot】 总结——》【MyBatis、MyBatis-Plus】 总结——》【Linux】 总结——》【MongoD…

【解决】idea启动spring MVC报错:一个或多个listeners启动失败Listener ClassNotFoundException

idea配置教程。tomcat调试报错Artifact :war exploded: Error during artifact deployment。 修改代码后&#xff0c;启动不生效&#xff0c;仍是旧代码。 根本原因是&#xff1a; Modules output path和Artifacts output directory不匹配 Modules output path一定要等于Ar…

网络编程 day 5

1、根据select TCP服务器流程图编写服务器 #include <myhead.h>#define ERR_MSG(msg) do{\fprintf(stderr, "__%d__:", __LINE__); \perror(msg);\ }while(0)#define PORT 8888 //端口号&#xff0c;范围1024~49151 #define IP "192.168.…

Uniapp中vuex的使用

vuex的学习笔记&#xff0c;很多地方还都不是很懂&#xff0c;先记下来再说&#xff0c;比小程序里自带的store复杂很多&#xff0c;看着头大&#xff0c;而且方法里面很多ES6的内容&#xff0c;头都看到爆炸 一、初始化vuex 新建store.js&#xff0c;挂载到main.js 1、在根…

Flink SQL你用了吗?

分析&回答 Flink 1.1.0&#xff1a;第一次引入 SQL 模块&#xff0c;并且提供 TableAPI&#xff0c;当然&#xff0c;这时候的功能还非常有限。Flink 1.3.0&#xff1a;在 Streaming SQL 上支持了 Retractions&#xff0c;显著提高了 Streaming SQL 的易用性&#xff0c;使…

前端性能优化

前言 性能优化这个问题&#xff0c;在面试的过程中问道的概率还挺大的&#xff0c;特别是对有前端开发经验的面试者来说&#xff0c;基本会被面试官问道关于性能优化的问题。但是在我们做项目的过程中&#xff0c;可能业务比较简单&#xff0c;并没有复杂到需要专门去优化的程…