Unity性能优化一本通
文章目录
- 关于Unity性能优化
- 一、资源部分:
- 1、图片
- 1.1、 图片尺寸越小越好
- 1.2、使用2N次幂大小
- 1.3、取消勾选Read/Write Enabled
- 1.4、图片压缩
- 1.5、禁用多余的Mip Map
- 1.6、合并图集
- 2、模型
- 2.1.限制模型面数
- 2.2.限制贴图的大小
- 2.3.禁用Read/Write Enables
- 2.4.不勾选其他辅助功能
- 2.5.调整网格压缩
- 2.6.使用LOD技术
- 3、字体
- 3.1.区分字何功能
- 3.2.制作字体
- 二、代码部分
- 1.AssetBundle文件
- 2.建立对象池管理资源
- 3.留意装箱拆箱
- 4.事件注册移除
- 5.物体寻找
- 6.可见性设置
- 7.静态类
- 8.避免重复
- 9.数据类型
- 10.字串操作
- 11.使用枚举和常量
- 12.反射和动态
- 13.避免try catch
- 14.避免Camera.main找摄像机
- 三、托管部分:
- 1、什么是托管
- 1.1、托管介绍
- 1.2、什么内存碎片和扩展
- 2、如何处理
- 2.1、减少临时分配
- 2.2、内存复用
- 2.3、避免拆箱装箱
- 2.4、避免闭包和匿名函数
- 总结:
关于Unity性能优化
总结内存的优化主要分为以下三部分,资源,代码和托管。资源部分往往是大头,很多情况下都能占据工程的内存70%~80以上的大小,所以这一部分的优化至关重要。
一、资源部分:
1、图片
关于纹理主要检查以下几个部分:
-图片大小
-压缩格式
-导入设置
从性能优化的角度上看,图片的处理有以下几个事需要做:
1.1、 图片尺寸越小越好
按需求而定,在够用的情况下,越小越好。需要知道的是1024X1024的图片大小将是512X512的四倍,而不是二倍。如下图是1024大小3m,而512只有0.8m.
而然这只是图片大小,当使用时放到内存中将会进一步增大。
1.2、使用2N次幂大小
由于Unity对2的N次幂大小的图片处理更为友好,尽量使用此尺寸大小。
1.3、取消勾选Read/Write Enabled
当勾选此选项时,该图片将会在CPU中多存一份备份让CPU访问,如果没有读写需求可以请关闭此选项。
1.4、图片压缩
在你选压缩格式以前,Unity本身会对图片有一部分处理,转换为我们工程中使用的Texture 2D。
为什么转换好了格式还需要我们选择压缩的方式呢?因为Unity有个明显的优势即平台的通用与适配性。
因而对单一平台的处理会相对薄弱,而平台的性能优势又不尽相同。所以我们需要根据平台的来选择。
格式 | 内存占用 | 质量 | 透明 | 二次方大小 | 建议使用场景 |
---|---|---|---|---|---|
RGBA32 | 1 | 100% | 有 | 无需要 | 清晰度要求极高 |
RGBA16+Dithering | 1/2 | 80% | 有 | 无需要 | UI、头像、不带渐变、颜色不丰富 |
RGBA16 | 1/2 | 60% | 有 | 无需要 | UI、头像、不带渐变、颜色不丰富、不拉伸放大 |
RGB16+Dithering | 1/2 | 80% | 无 | 无需要 | UI、头像、不透明、不拉伸放大 |
RGB16 | 1/2 | 60% | 无 | 无需要 | UI、头像、不透明、不渐变、不拉伸放大 |
RGB(ETC1)+Alpha(ETC1) | 1/4 | 60% | 有 | 需要,可长宽不同 | 尽可能使用,不满足要求再考虑上列格式 |
RGB(ETC1) | 1/8 | 60% | 无 | 需要,可长宽不同 | 尽可能使用,不满足要求再考虑上列格式 |
PVRTC4 | 1/8 | 40% | 无 | 需要,长宽相同 | 尽可能使用,不满足要求再考虑上列格式 |
RGBA32通常作为一种高保真的压缩格式,质量好性能消耗大。
而RBGA16+Dithering可以理解为RBGA32的阉割版,色彩分级大,过度也不够顺滑。
最后ETC1+Alpha/PVRTC4则是移动端常用的压缩格式,性能上有明显的优势。
1.5、禁用多余的Mip Map
类似于模型的Lod(Level of Detail)技术,会根据距离远近来展示图片的精度。
可以节省部分性能,但Mip map会增大部分内存,因而UI则没有必要开启功能。
当一张Texture开启Mipmap后,占用的内存将会是原来的4/3.
1.6、合并图集
合并图集优化的是图片渲染中Draw Call数量,基本原理即是将会经常一起出现的图片合并成一张图,当需要渲染的时候就一起发送给GPU去渲染。
由于DrawCall是由CPU调用GPU的命令,从而可以提升CPU的性能表现。
通过Edit > Project Setting > Editor > Sprite Packer > Mode > Always Enabled(Legacy Sprite Packer)
然后图片上就可以通过Packing Tag命名来区分合并的包了
通过Windows > 2D > Sprite Packer 可以打开图集窗口 点击Pack即可合并
2、模型
模型的优化更多的是建模人员的内容,模型的规范等。
2.1.限制模型面数
我们知道模型的构成即是由一个个点连成三角面,再由一个个三角面堆叠而成的。
所以面数的多少在一定程度上会影响模型文件的大小,所以不能无限制的添加。
2.2.限制贴图的大小
贴图会影响到模型的精细度,因而也会一定程序上影响大小。具体原理参照上面的图片部分讲解。
这部分也是容易被忽略的部分。
2.3.禁用Read/Write Enables
这个和图片的有点类似,打开后也会在CPU中保留一份Mesh数据让脚本访问,
在游戏当不需要对模型进行操作的时候则关闭此选项。
默认是禁用的,优化时可以排查一下。
2.4.不勾选其他辅助功能
与Reader/Write Enables类似,基本上在Unity中都是需要消耗一定资源去维护的。
因为未明确功能及需求不要点开。
2.5.调整网格压缩
调整Mesh Compression,此选项可以调整模型网格的压缩率,降低精度,从而获得性能的提升。
调整Optimize Mesh: 默认勾选的,确定三角形的网格中列出的顺序,获得更好的性能。
调整Normal:是否导入法线数据,默认导入,如果不需要做光照处理可以关闭。
2.6.使用LOD技术
这个是Unity提供的一个基于距离来决定展示精细度的功能,模型需要准备好指定内容的高、中、低模。
距离近的时候展示高模型,远一些时候使用中模,最远使用低模。
但这个技术也有个缺点,会大大增加模型工作量,同时也会让工程的包体变的巨大。
3、字体
3.1.区分字何功能
字体包有的含有中、英文,而有的则只是有英文。这点也非常容易被忽略,
如果一个字体我们只需要用到英文部分则,则应当优先考虑使用只有英文字体的包。
3.2.制作字体
此外如果字体我们只需要用到其中的小部分字符,我们可以考虑使用BMFont等字体
制作插件,制作自己独有的字体,以减少资源的大小。
字体少则1m,大的有数十兆,个人认为这点非常重要。可以考虑和美术同学协同优化。
总体而言,资源部分在满足效果需求的情况下,应该越小越好。
二、代码部分
1.AssetBundle文件
AssetBundle加载后要使用Unload卸载镜像文件
AssetBundle文件下载后可以考虑存本地作为缓存
2.建立对象池管理资源
什么是对象池资源太多了,自行查阅吧 Y(^ _ ^)Y,这里不坠述了。
3.留意装箱拆箱
避免装箱拆箱操作比如yield返回值、Foreach、ArrayList等…
4.事件注册移除
-比方说,Button.onClick.AddListener()加载的按钮事件,使用后则需要使用:Button.onClick.RemoveListener()来移除。-Evnet中的+=事件,需要使用-=来移除
否则将因为内容一直被引用而点用,可能造成内存泄露。
5.物体寻找
避免 频繁大量
Find()或GetComponent()函数.因为他会在当前全场景中搜索,产生较高开销。
可以考虑使用MonoBehaviour脚本下挂载引导,以减少搜索次数。
6.可见性设置
在非静态类中,全局变量会在该类补实例化过程中占用资料,而非局部变量则会在方便使用过程中占用资源。
7.静态类
非静态类会在实例化后占用资料,而静态类则会在首次补调用后,在程序中一直存在。
因而不要过多的使用静态类。
8.避免重复
需要注意在Update或for等循环、递归结构中的资源使用。在这些结果中通常重复次数较多,则容易产生大量的资源使用。比如就不要在Update中不断的实例化、销毁物体,而因考虑使用对像池。
9.数据类型
刚开始学习的时候我也很不理解,既然int和float都能存放数字,为什么需要区分开?
后面才知道他们占用的空间是不同的。在够用的情况下,我们应当使用更清量级的数据类型。
同理,选择数组时也当如此。
10.字串操作
避免大量的String操作,因为会产生大量的内存分配。实在有需要,则可以考虑使用StringBuffer进行优化。
11.使用枚举和常量
有时候我们在代码中有些莫名奇妙的数字,开发者自己当时知道是什么含义,时间长了可能会忘记,也不利于别人阅读。
因而推荐使用数字和常量,因为它们可以命名,从而提高代码的可读性。
12.反射和动态
避免过多使用发射和动态代码,因为他们的性能消耗会更大。
13.避免try catch
增经小白的我也想过,既然这个可以放置报错,我所有地方都不做空判断,直接使try catch不就好了。
其实这个语句结构体内有大量性能消耗。
14.避免Camera.main找摄像机
没想到吧,这个也消耗性能。不过细想每次都去找,当然会有消耗。找个变量存起来就好了。
三、托管部分:
1、什么是托管
1.1、托管介绍
Unity的托管内存系统是基于Mono或Il2CPP虚拟机之上的C#环境。所有托管代码中被创建的对像都会被分配到托管堆上,所有不为空的引用对象和值类型对象都将放置在托管堆上。当在脚本中不包含对像的任何引用时,系统将自动释放这部分内存。
个人推荐脑袋里要有下面一个图,内存的占用像是是一箱箱货物,需要有足够的空间来存放。废弃后的清理也有延迟,那么如何合理的分配和使用空间?我们来探讨一下。
1.2、什么内存碎片和扩展
内存空间类似于一个个小格子,有的数据类型需要占用2格,有的则是4格、8格,紧密排列在一起。
当有数据补释放时,这些格子会重新被空出来。这时这些格子只能存放小于等于
这中间格子大小的
数据。这样就有可能有些空格子并没存到数据,这种情况称为 内容碎片
,而当新的数据托管不足
矣存放时,则会申请更大的托管空间来存放。
2、如何处理
2.1、减少临时分配
部分项目中会出现每帧分配上百kb的临时数据,这非常影响性能。因为这些临时数据无法马上被释放
有可能导致堆长度不够而申请更大的长度。而托管堆申请的内存长度是不会反还的,会导致占用内存过大。
2.2、内存复用
尽量复用数组、集合、对象等。尽量避免新分配内存空间。
比如在Update中New一个List进行计算,就不如将List放在循环体外,每次Update使用Clear()清空后复用。
2.3、避免拆箱装箱
这是C#语言用于临时分配较小内存会被分代垃圾收集器和分配大小的而被开发出来的。
但由于不能有效处理小的、频繁产生的临时垃圾,所以我们要避免装箱拆箱操作比如:
yield返回值、Foreach、ArrayList等…
2.4、避免闭包和匿名函数
因为在编译IL代码时,闭包和匿名函数装会被New成一个Class
总结:
性能优化往往就是在了解程序与资源的运行规则后,根据具体项目合理分配资源。有时间也难免做出一些取舍拆东墙补西墙不善尽美。 希望大家可以活学活用。文章整理出来的是我上一篇文章的延伸,更细化一点的内容,希望对大家有帮助。谢谢观看。
相关文章:

Unity性能优化一本通
文章目录 关于Unity性能优化一、资源部分:1、图片1.1、 图片尺寸越小越好1.2、使用2N次幂大小1.3、取消勾选Read/Write Enabled1.4、图片压缩1.5、禁用多余的Mip Map1.6、合并图集 2、模型2.1.限制模型面数2.2.限制贴图的大小2.3.禁用Read/Write Enables2.4.不勾选其…...

Mysql,SqlServer,Oracle获取库名 表名 列名
先看下需求背景: 获取某个数据源连接下所有库名,库下所有表名,表中所有字段 1.MySql 先说MySql吧,最简单 1.1获得所有数据库库名 这是一个mysql和sqlserver公用的方法,这里url不用担心数据库问题,他其实…...

errno变量和显示错误信息
一、errno Linux很多函数发生错误,只会返回-1。因此,我们只知道函数发生了错误,却不知道具体发生了什么错误。 因此Linux 系统下对常见的错误做了一个编号,每一个编号都代表着每一种不同的错误类型。 发生错误时,对…...
Centos 7 安装 Docker Enginee
文章目录 Centos 安装 Docker Enginee系统要求卸载旧版本使用 RPM 仓库设置 Docker 仓库安装 Docker Enginee升级 Docker Enginee 卸载 Docker Centos 安装 Docker Enginee 要在 Centos 安装 Docker Enginee,需要满足以下要求: 系统要求 CentOS 7Cent…...

通过js来实现用身份证号来判断性别和出生年月
html: <input type"text" id"shenfenzhenghao" oninput"hao()" placeholder"证件号"><input type"text" id"xingbie" disabled"disabled" placeholder"性别"><input type&qu…...

华为数通方向HCIP-DataCom H12-831题库(多选题:61-80)
第61题 在MPLS VPN中,为了区分使用相同地址空间的IPV4前缀,将IPV4的地址增加了RD值,下列选项描述正确的是: A、在PE设备上,每一个VPN实例都对应一个RD值,同一PE设备上,必须保证RD值唯一 B、RD可用于来控制VPN路由信息的发布 C、RD在传递过程中作为BGP的扩展团体性封装在…...
【T】03
A 【模板】快速幂 板子,略 #include<bits/stdc.h> #define ll long long using namespace std; ll a,p,k; int main() {scanf("%lld%lld%lld",&a,&p,&k);printf("%lld^%lld mod %lld",a,p,k);ll ans1,wa;a%k;while(p){if(p…...

VBA技术资料MF73:将Logo添加到页眉侧
我给VBA的定义:VBA是个人小型自动化处理的有效工具。利用好了,可以大大提高自己的工作效率,而且可以提高数据的准确度。我的教程一共九套,分为初级、中级、高级三大部分。是对VBA的系统讲解,从简单的入门,到…...
听GPT 讲Rust源代码--library/std(1)
std git:(master) ✗ tree.├── Cargo.toml├── benches│ ├── hash│ │ ├── map.rs│ │ ├── mod.rs│ │ └── set_ops.rs│ └── lib.rs├── build.rs├── src│ ├── alloc.rs│ ├── ascii.rs│ ├── backtrace│ │…...
Vue源码总结
1,根据vue工程package.json配置文件查看scripts命令,找到build命令执行的js文件 2,根据构建执行的js文件继续跟进,找到主入口文件 3,从主入口文件直接分析主干代码,追踪export的Vue对象 4,跟…...
记一次调试微信订阅消息的坑
微信发送订阅消息文档 发送订阅消息 | 微信开放文档 按照文档说明的,一直报data param错误,编码47001,从程序中把请求参数扣出来,放到微信提供的工具里面调试 微信调试工具 然后报data参数要用string,转化为string…...

ASP.NET Core3.1 API 创建(Swagger配置、数据库连接Sql Server)、开发、部署
文章目录 创建项目点击Nuget安装包删除原有controllers编辑新建controll、添加注释Startup 注册Swagger服务使用swagger中间件配置XML注释更改启动端口 launchsettings.json在startup.cs跨域处理运行 数据库设计与连接安装库新建类继承框架根据数据库表设计对应设计类在DataCon…...
大数据之LibrA数据库常见术语(八)
SCTP Stream Control Transmission Protocol,流控制传输协议。是IETF于2000年新定义的一个传输层协议。是提供基于不可靠传输业务的协议之上的可靠的数据报传输协议。SCTP的设计用于通过IP网传输SCN窄带信令消息。 Session 数据库系统在接收到应用程序的连接请求时…...

【实战】Kubernetes安装持久化工具NFS-StorageClass
文章目录 前言技术积累存储类(storage class)什么是NFS什么是PV\PVC为什么要用NFS-StorageClass 安装NFS-StorageClass保证K8S集群正常投用安装NFS工具与客户端NFS安装常见错误安装NFS-StorageClass存储器 前言 前面的博文我们介绍了如何用kuberadmin的…...
透明安全地解释Moonbeam基金会分配的GLMR去了哪
在GLMR分配比例中,约有16.7%的GLMR分配给了生态支持。这部分GLMR究竟用在了哪里,Moonbeam生态是否还有足够的GLMR扶持生态项目? Moonbeam基金会每隔半年会发布一份GLMR透明度报告,最近的报告日期为2023年7月31日。其中列出了社区…...

python安装包失败 安装scipy包
最近在配深度学习环境,安装好了conda、CUDA、cuDNN,运行之后报错,没有scipy包。 试了很多方法: 用命令行pip、conda install 在pycharm下载包 在环境中添加包 都失败了 要么直接ERROR,要么超时 问了师兄 需要在conda环…...

解决javascript报错:SyntaxError: Invalid Unicode escape sequence
在处理cookie时报这个错: 网上搜了一圈都说是反斜杠问题,要把\替换成/ 但是试了网上的replace替换: replace(/\\/g, /) 结果没有用!!! 然后我干脆直接做了一个最简单字符串赋值,再打印出来。…...
【Python第三方包】使用Python的Translate包进行文本翻译
文章目录 前言一、Translator类的初始化参数二、translate函数三、翻译示例代码1.1 示例代码11.2 示例代码2总结前言 在现代互联网时代,跨语言翻译已经成为了不可或缺的工具。不仅对于个人,对于企业和开发者来说,实现文本翻译在国际化、多语言支持以及内容本地化方面都具有…...

【OpenCV实现图像阈值处理】
文章目录 概要简单阈值调整自适应阈值调整大津(Otsus)阈值法Otsus 二值化是如何工作的 概要 OpenCV库中的图像处理技术,主要分为几何变换、图像阈值调整和平滑处理三个部分。 在几何变换方面,OpenCV提供了cv.warpAffine和cv.warpPerspective函数&#…...
【Python机器学习】零基础掌握StackingRegressor集成学习
如何更准确地预测糖尿病患者的血糖水平? 糖尿病是一种影响全球数百万人的慢性疾病。有效地管理和预测血糖水平是糖尿病患者日常生活的重要一环。单一的预测模型(比如线性回归、支持向量机等)虽然有一定的效果,但在处理复杂的医疗数据时,其准确性可能会受到限制。 为了准…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...
Java 语言特性(面试系列2)
一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...
利用ngx_stream_return_module构建简易 TCP/UDP 响应网关
一、模块概述 ngx_stream_return_module 提供了一个极简的指令: return <value>;在收到客户端连接后,立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量(如 $time_iso8601、$remote_addr 等)&a…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...
【Linux】C语言执行shell指令
在C语言中执行Shell指令 在C语言中,有几种方法可以执行Shell指令: 1. 使用system()函数 这是最简单的方法,包含在stdlib.h头文件中: #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...

基于Flask实现的医疗保险欺诈识别监测模型
基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施,由雇主和个人按一定比例缴纳保险费,建立社会医疗保险基金,支付雇员医疗费用的一种医疗保险制度, 它是促进社会文明和进步的…...

使用分级同态加密防御梯度泄漏
抽象 联邦学习 (FL) 支持跨分布式客户端进行协作模型训练,而无需共享原始数据,这使其成为在互联和自动驾驶汽车 (CAV) 等领域保护隐私的机器学习的一种很有前途的方法。然而,最近的研究表明&…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI
前一阵子在百度 AI 开发者大会上,看到基于小智 AI DIY 玩具的演示,感觉有点意思,想着自己也来试试。 如果只是想烧录现成的固件,乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外,还提供了基于网页版的 ESP LA…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明
AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...