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、避免闭包和匿名函数
  • 总结:

想拿《1024达人勋章》,帮忙点个赞,谢谢。

关于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有个明显的优势即平台的通用与适配性。
因而对单一平台的处理会相对薄弱,而平台的性能优势又不尽相同。所以我们需要根据平台的来选择。

格式内存占用质量透明二次方大小建议使用场景
RGBA321100%无需要清晰度要求极高
RGBA16+Dithering1/280%无需要UI、头像、不带渐变、颜色不丰富
RGBA161/260%无需要UI、头像、不带渐变、颜色不丰富、不拉伸放大
RGB16+Dithering1/280%无需要UI、头像、不透明、不拉伸放大
RGB161/260%无需要UI、头像、不透明、不渐变、不拉伸放大
RGB(ETC1)+Alpha(ETC1)1/460%需要,可长宽不同尽可能使用,不满足要求再考虑上列格式
RGB(ETC1)1/860%需要,可长宽不同尽可能使用,不满足要求再考虑上列格式
PVRTC41/840%需要,长宽相同尽可能使用,不满足要求再考虑上列格式

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


总结:

性能优化往往就是在了解程序与资源的运行规则后,根据具体项目合理分配资源。有时间也难免做出一些取舍拆东墙补西墙不善尽美。 希望大家可以活学活用。文章整理出来的是我上一篇文章的延伸,更细化一点的内容,希望对大家有帮助。谢谢观看。

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

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

相关文章

学习笔记:二分图

二分图 引入 二分图又被称为二部图。 二分图就是可以二分答案的图。 二分图是节点由两个集合组成,且两个集合内部没有边的图。换言之,存在一种方案,将节点划分成满足以上性质的两个集合。 性质 如果两个集合中的点分别染成黑色和白色&am…

Pytorch代码入门学习之分类任务(二):定义数据集

一、导包 import torch import torchvision import torchvision.transforms as transforms 二、下载数据集 2.1 代码展示 # 定义数据加载进来后的初始化操作: transform transforms.Compose([# 张量转换:transforms.ToTensor(),# 归一化操作&#x…

【QT开发(15)】QT在没有桌面的系统中可以使用

在没有桌面的系统中,可以使用QT库。QT库可以在没有图形用户界面(GUI)的环境中运行,例如在服务器或命令行终端中。 这样就可利用Qt的: 对象模型,信号和槽容器类多线程和多进程网络编程 等

wiresharak捕获DNS

DNS解析: 过滤项输入dns: dns查询报文 应答报文: 事务id相同,flag里 QR字段1,表示响应,answers rrs变成了2. 并且响应报文多了Answers 再具体一点,得到解析出的ip地址(最底下的add…

CentOS 编译安装 nginx

CentOS 编译安装 nginx 修改 yum 源地址为 阿里云 curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repoyum makecache升级内核和软件 yum -y update安装常用软件和依赖 yum -y install gcc gcc-c make cmake zlib zlib-devel openss…

环形链表(C++解法)

题目 给你一个链表的头节点 head ,判断链表中是否有环。 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置&#…

【计算机网络】认识协议

目录 一、应用层二、协议三、序列化和反序列化 一、应用层 之前的socket编程,都是在通过系统调用层面,如今我们来向上打通计算机网络。认识应用层的协议和序列化与反序列化 我们程序员写的一个个解决我们实际问题, 满足我们日常需求的网络程序, 都是在应…

前端《中国象棋》游戏

源码下载地址 支持:远程部署/安装/调试、讲解、二次开发/修改/定制 查看视频 本程序是一个基于Html/css/javascrip的网页端象棋APP,其中引入JQuery来简便开发。 在程序中,使用一个Map二维数组来表示棋盘,通过给棋子设置不同的横坐…

FileWriter文件字符输出流

一.概念 以内存为基准,把内存中的数据以字符形式写出到文件中 二.构造器 public FileWriter(Filefile) 创建字节输出流管道与源文件对象接通 public FileWriter(String filepath) 创建字节输出流管道与源文件路径接通 public Filewriter(File file,boolean append) …

【MySQL】并发事务产生的问题及事务隔离级别

先来复习一下事务的四大特性: 原子性(Atomicity):事务是不可分割的最小操作单位,事务中的所有操作要么全部执行成功,要么全部失败回滚,不能只执行其中一部分操作。一致性(Consisten…

卷积神经网络的感受野

经典目标检测和最新目标跟踪都用到了RPN(region proposal network),锚框(anchor)是RPN的基础,感受野(receptive field, RF)是anchor的基础。本文介绍感受野及其计算方法,和有效感受野概念。 1.感受野概念 在典型CNN结构中,FC层(…

vue核心面试题汇总【查缺补漏】

给大家推荐一个实用面试题库 1、前端面试题库 (面试必备) 推荐:★★★★★ 地址:web前端面试题库 很喜欢‘万变不离其宗’这句话,希望在不断的思考和总结中找到Vue中的宗,来解答面试官抛出的…

FPGA设计时序约束七、设置时钟不确定约束

一、背景 在之前的时序分析中,通常是假定时钟是稳定理想的,即设置主时钟周期后按照周期精确的进行边沿跳动。在实际中,时钟是非理想存在较多不确定的影响,存在时延和波形的变化,要准确分析时序也需将其考虑进来&#x…

06 _ 链表(上):如何实现LRU缓存淘汰算法

今天我们来聊聊“链表(Linked list)”这个数据结构。学习链表有什么用呢?为了回答这个问题,我们先来讨论一个经典的链表应用场景,那就是LRU缓存淘汰算法。 缓存是一种提高数据读取性能的技术,在硬件设计、软件开发中都有着非常广泛的应用,比如常见的CPU缓存、数据库缓存…

“节省内存、提升性能:享元模式的神奇之处“

概念 享元模式的本质是缓存共享对象,降低内存消耗。 是对象池的的一种实现,一句话用到了缓存了对方和池化技术的地方绝大多是享元模式的体现。 例如线程池,数据库连接池,字符串常量池 应用示例 String中的享元模式 public c…

Linux Centos7安装后,无法查询到IP地址,无ens0,只有lo和ens33的解决方案

文章目录 前言1 查看network-scripts目录2 创建并配置 ifcfg-ens33 文件3 禁用NetworkManager4 重新启动网络服务总结 前言 在VMware中,安装Linux centos7操作系统后,想查询本机的IP地址,执行ifconfig命令 ifconfig结果如下: 结…

​ iOS自动混淆测试处理笔记

1 打开 ipa,导出ipa 路径和配置文件路径会自动填充 ​ 2 点击 开始自动混淆测试处理 自动混淆测试是针对 oc 类和oc方法这两个模块进行自动混淆ipa,并ipa安装到设备中运行,通过检测运行ipa包是否崩溃,来对oc类和oc方法进行筛选。…

Docker Harbor概述及构建

Docker Harbor概述及构建 一、Docker Harbor 概述1.1、harbor 简介1.2、Harbor的优势1.3、Harbor 的核心组件1.4、Docker私有仓库 架构 二、Harbor构建Docker私有仓库2.1 环境配置2.2、部署Harbor服务2.2.1、上传dock-compose,并设置权限2.2.2、安装harbor-offline-…

openEuler 22.03 LTS 环境使用 Docker Compose 一键部署 JumpServer (all-in-one 模式)

环境回顾 上一篇文章中,我们讲解了 openEuler 22.03 LTS 安装 Docker CE 和 Dcoker Compose,部署的软件环境版本分别如下: OS 系统:openEuler 22.03 LTS(openEuler-22.03-LTS-x86_64-dvd.iso)Docker Engine:Docker C…

归并排序(java)

大家好我是苏麟 , 今天说说归并排序 . 归并排序 递归 正式学习归并排序之前,我们得先学习一下递归算法。 定义: 定义方法时,在方法内部调用方法本身,称之为递归. public void show(){System.out.println("aaaa")…