Unity性能优化

大的方面来说,通过Unity对于项目的性能优化大概可以分为下面几个部分:

  • 资源
  • 渲染
  • 程序
  • 项目配置

而在这个部分中,资源的性能优化属于最基础、最有效的优化手段,也是游戏开发者日常开发最需要注意的一部分,所以本篇文章就简单的介绍一下对资源进行操作时需要关注哪些点

一、纹理(简单来说就是图片)

纹理的资源优化主要集中于下面的几点:

  • 纹理大小
  • 压缩格式
  • 导入设置

通常,在游戏运行时,大部分内存都是用在了纹理上,因此你的导入设置非常关键,我们可以在Inspector面板看到图片资源的信息,类似于下面这张图:

从性能优化的角度看,纹理导入需要遵循如下的原则:

  • 降低最大分辨率
  • 采用二次幂压缩格式:
  • 制作纹理图集
  • 取消勾选Read/Write Enabled
  • 禁用多余的Mip MapMip Map贴图在2D精灵和UI图形这类大小始终一直的纹理上并无用处

1、降低最大分辨率

很好理解,纹理分辨率越大,在游戏运行时,占用的内存资源越大,并且占用的内存量是与其分辨率的平方成正比的。也就是说,分辨率变为原来的二倍,那么内存量就需要消耗四倍。因此需要从资源优化的角度来讲,需要对其进行一定的限制,简单的来说,一个Button的纹理通常低于128X128,如果使用1024X024规格的大小就造成了性能的浪费

如下面的图,我们可以在图片资源的Inspector面板中最下面的属性中看到它:Max Size,同时可以看到可以根据不同平台来选择不同的最大分辨率:

第一张图片:Max Size调整为1024,纹理资源大小为4.9MB

第二张图片:Max Size调整为512,图片资源大小为1.3MB

2、对于纹理的压缩

在你主动选择压缩格式之前,Unity本身会对图片做一些处理,无论你放入的是PNGJPGPSD或者TGAUnity都会手动帮助我们调整为Texture 2D,这是一种简单的调度策略:

那么既然Unity本身都已经智能转换好了,为什么还要给予开发者选择压缩格式的选择呢,直接对Texture 2D封装好压缩方法不就可以了吗?

其实Unity相对于其他开发引擎有一个很明显的优势,就是多适配性,那么为了实现这种多适配性,对于单一平台的针对性就会相对减弱,而不同平台的性能表现又不尽相同,就需要开发者来根据平台特点来选择针对游戏平台的压缩格式。

同样,即使在同一平台,也会根据不同的情况有着不同的压缩需求,比如有一些关键的主页面图片,玩家感知强的地方,就对图片的质量要求高些,一些边角的辅助图片,可能要求就低一些,如果都使用高质量压缩,性能方面就造成了浪费,但若都是用低质量压缩,质量又跟不上。所以,同样需要根据实际需求选择不同的压缩格式。

在说到Unity图片压缩时,经常会看到这样一张图,来介绍不同压缩格式的特点与适用场景,我也是百度图片直接爬取的这张图片,大家可以参考着来看(如果有侵权,请告知我,我会立刻删除)

在理解上面这张图之前做一个简单的计算,一张10241024RGBA32格式图片的占用存储空间为:

由于RGBA32一个像素每一个颜色值是由两个16进制的数组成,也就是8位,那个一个像素就是8位乘以4个颜色值RGBA得到的是4个字节,即4B,然后乘上1024*1024个像素,最终得到的大小为4MB,也就是4兆。很明显这是很恐怖的一个数字,要知道现在移动端手机的运行内存大概6G,除去系统的占用内存,真正给游戏用的最多也就4G`,再分配给GPU|的显存就更少了,而若这些内存被用来大量加载贴图很明显是不能被接受的。同时,这样数据量的图片加载也会给内存

基于上面原生纹理带来的包体与内存问题,就需要根据不同的情况采取一些压缩策略,由于本人基本没有美术功底,所以对与各种压缩格式的美术呈现效果不是很了解,主要是从功能性与性能的角度来分析各种压缩格式的适用场景:

  • 高品质压缩格式:RGBA32作为一种高保真的压缩格式,能够极大的保证图片质量

  • 中品质压缩格式:RGBA16 + Dithering一听就是RGBA32的阉割版,简单来说,相比于RGBA32其色彩细分程度大,可以明显的看出阶梯感,视觉表现相对于RGB32不够平滑

  • 低品质压缩格式: ETC1+Alpha/PVRTC4这些压缩格式往往是移动段最常用的压缩格式,其相对于其他压缩格式有着无可比拟的性能优势

注意:

  • 除了由于压缩逻辑不同带来的加载带宽减少之外,同时还需要了解像ETC1PVRTC4等这类在内存中不需要进行解压,而是可以直接被GPU支持,所以相比其他压缩格式通常会有最好的性能表现

3、取消勾选Read/Write Enabled

该功能是为了使得游戏开发者可以通过C#脚本调用对与图片的读取与写入的控制,很明显,这是由CPU来控制实现的,所以为了可以使得CPU获取数据,需要在内存中备份一份让CPU访问。同时为了图形渲染与显示,又会将其加载到显存中为GPU提供数据。

简单来说,该选项会在游戏运行时,分别在CPU内存与GPU内存中备份出一张贴图,如果你并不需要对于纹理进行读写操作,可以尝试关闭该选项,这样就可以避免游戏运行时占用多余的内存

4、禁用多余的Mip Map

Mip Map类似于模型的LOD,同样是一种基于渲染距离改变渲染贴图精度的技术。其优势是在物体距离渲染距离比较远时,可以节省性能。但是使用Mip Map时会增大内存占用量。

Mip map的技术原理是根据原始图进行2的幂次方的递减来生成一组不同精度的图片。当游戏运行时,会将这组图片加载到内存中,然后根据渲染的距离不同,来使用不同精度的图片。

Mip map会增大多大的内存占用量呢

  • 在我们使用Mip map时,假设大小为256X256,并且会生成8张不同精度的图片。根据2的幂次方进行递减计算每张贴图大小并累加。这样最终得到的图片组的体积大概比原来的单张贴图大33%

通过一个实例来验证,假设原始图片大小为8M,生成的第一张低精度图片的大小为2M(分辨率减少一半,大小就会变为原来的四分之一,很好理解)这样大概递减8次,然后累加,就会获取最终的图片组大小,通过一个简单的递归方法来计算一下:

    public void Awake(){Debug.Log(GetMipmapSize(8, 8)/8);}// index:处理总层级数 imageSize:初始大小 返回增大的内存量float GetMipmapSize(int index,float imageSize){float lastSize = 0;if (index == 1){lastSize = imageSize*0.25f;}if (index > 1){lastSize = imageSize * 0.25f + GetMipmapSize(index - 1, imageSize * 0.25f);}return lastSize;}

执行程序,得到的结果为:

可以看到,求到的结果是接近于33%,当然如果Mip Map对一张纹理的处理不是八次,计算的结果会有偏差但是实际上,从三次往上,内存占用量的增加比例已经非常少了,基本都维持在33%左右,将上面的代码稍微修改,做个小验证:

     public void Awake(){for (int i = 3; i < 15; i++){Debug.Log(string.Format("处理 {0} 次内存占用量为: {1}",i,GetMipmapSize(i, 8) / 8));}        }float GetMipmapSize(int index,float imageSize){float lastSize = 0;if (index == 1){lastSize = imageSize*0.25f;}if (index > 1){lastSize = imageSize * 0.25f + GetMipmapSize(index - 1, imageSize * 0.25f);}return lastSize;}

得到的日志为:

可以发现,从三层开始,基本就维持在33%的内存占用量,并且在层数逐渐增大的时候,内存占用量增加量就非常非常少了。

Unity所支持的纹理最小为32X32,也就是最小的纹理也会额外的产生三层低精度纹理:16X164X41X1,这就是为什么很多文章介绍到使用Map mip会说其大约会增加33%的内存占用量

虽然Mip map本身是一种性能优化的技术,但是在2D精灵或者UI元素这些不会改变渲染精度的纹理上,只会占用多余的内存,所以在2D精灵或者UI元素上使用纹理时记得不要勾选Mip map

5、打包图集

图集的打包主要是优化UI图形渲染过程中Draw call的数量,其基本原理也是通过UI元素合批来减少Draw Call,进入提升CPU的性能表现,关于其具体细节,可以查看我之前的文章:

图集打包文章:

  • Unity 将Sprite打包进图集

二、模型

相比与纹理,模型的性能表现更多的取决于美术规范,程序来讲没有更多可以优化的地方,但是在Unity中也有一些选项影响模型加载、渲染等方面的性能表现,我们可以在导入时看到:

1、禁用掉Reader/Write Enables:

点击模型,可以在Inspector面板看到这些设置选项,类似于纹理,如果在游戏中,你不需要对模型进行修改,可以禁用掉Reader/Write Enables来避免数据的备份而占用多余的内存,我们可以在Unity官方文档中找到相关介绍:

翻译过来就是:

  • 启用此选项后,Unity 会将 Mesh数据上传到 GPU可寻址内存,但也会将其保存在 CPU 可寻址内存中。这意味着Unity可以在运行时访问 Mesh数据,可以从脚本中访问它。

  • 而禁用此选项后,Unity 会将 Mesh 数据上传到 GPU可寻址内存,然后将其从 CPU 可寻址内存中删除

  • 默认情况下,此选项处于禁用状态。在大多数情况下,要节省运行时内存使用量,请禁用此选项

而对于模型本身来说,尽量避免模型留有多余的面数。尤其是移动端。因为高精度模型除了本身所带来的压力外,在其他方面也有诸多的性能挑战

注意:

  • 某些情况下禁用Reader/Write Enables会使得Mesh Collider不可用,具体信息在Unity官方文档中有提到:

2、尽量不要勾选不需要的功能选项

Unity中,某些功能即使你未使用到,也会 消耗一定的资源去维护其状态。类似上面的Reader/Write Enables选项,所以用不到的功能我们可以考虑尽量的去禁用掉

3、设置一些关于质量与性能的选项

Unity提供了一些对模型进行优化的选项,可以查阅Unity官方文档来阅读了解他们,这里也简要的列出:

通过上面一张图片可以看出,影响模型表现与游戏性能的选项有下面几个:

  • Mesh Compression:通过使用网格边界和每个组件较低的位深度来压缩网格数据,增加压缩率会降低网格的精度。最好在 Mesh 看起来与未压缩版本没有太大区别的情况下将其调得尽可能高。这对于优化游戏大小很有用
  • Optimize Mesh:确定三角形在网格中列出的顺序以获得更好的 GPU 性能,默认都会勾选
  • Normals:如果网格模型既不是法线贴图也不受实时光照影响,就选用None,这样也能够很好的提升性能表现

其实,Unity设置了一些通过程序控制模型质量来改变性能表现的选项,但是不建议使用,预期通过这些选项来调整性能表现,还不如直接让美术直接处理模型。毕竟他们更加专业,可以更好的保证模型的表现效果与性能表现的平衡。

4、使用LOD

关于LOD,其实应该在渲染这一段来讲,但是这个技术又与模型网格有很大的关系,所以提前介绍一下

LODLevels of Detail,翻译过来就是多层次细节,类似与纹理渲染的Mip map技术,同样是一种根据渲染距离设置渲染精度的一种技术。其实现方式是在游戏开发时,美术根据不同的渲染距离制作一组不同精度的模型,导入到Unity通过LOD组件连接其这一组模型,并设置相关参数。这样在游戏运行时,就会在不同的距离有不同的渲染精度:

这是Unity官方文档的一个案例,可以看出,随着渲染距离的增加,渲染精度逐渐下降,直到最终被剔除,这样做的优势是保证游戏画面表现的同时,可以最大程度降低渲染压力。简单的理解,如果不采用LOD,随着距离增加,物体占用的屏幕像素就会越少,那么单位像素的三角面数就会越多。单位的渲染压力就会增大。画面表现需求不高的地方渲染压力反而更高,这显然是不合理的。所以就需要通过LOD来解决这样的问题。

当然这种技术本身也是有相当大的缺陷的,首先就是会增大包体的体积,同时也会增加美术的工作量。所以在实际开放中,一般只会对一些重要的对象使用该技术

总结

上面所介绍的关于资源影响游戏性能的一些常用的点,都是游戏开发者日常接触最多的,更深入,更底层的就需要根据项目的特点进行专门的适配与调整。

Unity 性能优化:资源篇相关推荐

  1. Unity性能优化 – 脚本篇

    最近开始进行Unity性能优化的工作,主要分为三类:CPU.GPU和内存.由于我们游戏的核心战斗是计算密集型,所以主要是受限于CPU.CPU的优化又分为渲染和脚本,本文将着重于脚本优化. 一般来说,优 ...

  2. Unity性能优化 - Overdraw篇

    一.什么是Overdraw Unity Overdraw(超绘)是指在渲染过程中绘制了超过一次相同像素的现象.当多个UI元素重叠时,每个像素都需要被多次绘制.这种绘制超出了渲染所需的最小像素数,因此被 ...

  3. unity 性能优化--内存篇(上)

    资源内存占用 在一个较为复杂的大中型项目中,资源的内存占用往往占据了总体内存的70%以上.因此,资源使用是否恰当直接决定了项目的内存占用情况.一般来说,一款游戏项目的资源主要可分为如下几种:纹理(Te ...

  4. Unity性能优化 :合批篇

    前言 本系列为一些性能优化的小知识,是日常游戏开发中与性能表现的一些点,本篇为该系列文章的第二篇,前篇链接: 第一篇: Unity性能优化:资源篇 在早期Unity中,对于合批的处理手段主要是下面三种 ...

  5. Unity - 性能优化 - 包体,内存 - 偏静态资源的优化

    文章目录 静态资源优化 - AssetPostprocessor Texture 压缩 Model 网格.动画 压缩 音频压缩 纹理的优化经验 尺寸 通道 发布出来的包资源再次分析 如何工具快速定位静 ...

  6. 【Unity性能优化】静态资源优化——Audio优化

    文章目录 写在前面 1. 前言 2. 使用Asset Checker进行资源检测 3. Audio优化 3.1 启用Force to Mono 3.2 压缩格式与采样率 3.3 音乐加载类型 3.4 ...

  7. 由美团技术文章整理---spark性能优化基础篇--开发调优与资源参数调优

    文章地址1:Spark性能优化指南--基础篇 - 美团技术团队 文章地址2:Spark性能优化指南--高级篇 - 美团技术团队 目录 一.关于性能优化基础篇--开发调优 1.避免创建重复RDD (1) ...

  8. Unity性能优化(2)-官方教程Diagnosing performance problems using the Profiler window翻译

    http://www.cnblogs.com/alan777/p/6135703.html Unity性能优化(2)-官方教程Diagnosing performance problems using ...

  9. Unity3D性能优化——工具篇

    Quote from:https://zhuanlan.zhihu.com/p/39529241 性能优化是游戏项目开发中一个重要且必须的元素.用户和项目的需求在并且会持续增长.而即便在硬件设备高速发 ...

最新文章

  1. access2003安装包百度云_阿里云服务器安装JDK与配置环境详细步骤
  2. C和指针之部分理解和编码总结
  3. session会话拦截ajax,session过期,拦截ajax请求并跳转登录页面
  4. 热传导/物质扩散算法应用于推荐
  5. Java 实现固定长度队列,自动删除最早添加的数据
  6. VB6.0中创建和使用文本资源文件
  7. 002649:springboot下mybatis运行原理
  8. css中文本超出部分省略号代替
  9. N的倍数 51Nod - 1103 (抽屉原理)
  10. 2017大一计算机教程,2017年计算机等考一级章节考点:WPS2000新手入门教程
  11. conda报错-Collecting package metadata (current_repodata.json): failed
  12. html5做在线课件,HTML5教程:制作移动教育课件
  13. Ubuntu14.04更新显卡(Nvidia gt755m)驱动,成功步骤
  14. 如何改变python的背景颜色_怎样使用python改变背景颜色
  15. 《NVM-Express-1_4-2019.06.10-Ratified》学习笔记(8.8)-- Reservations
  16. java 创建二维码 并加载显示到窗口
  17. 个人小程序和企业小程序
  18. 智能小车 + 机械臂——华为嵌入式精英挑战赛
  19. vue 修改模板{{}}标签_vue.js - Vue单文件的template标签
  20. 云计算的二十个基本定义 不可不知!

热门文章

  1. Keras少量样本训练强大图像分类模型
  2. 【上海赛区】2022数学建模国赛获奖名单公布
  3. 基本排序算法 【转载】
  4. 用英雄联盟的方式讲解JavaScript设计模式!
  5. 新特性:TabLayout动态添加条目
  6. QComboBox下拉框条目高度的调整
  7. 工资3000,靠国际版抖音TikTok月入2W+:这个风口真的很赚钱!
  8. 苹果Swift编程语言入门教程【中文版】
  9. 使用excel公式vlookup提取多个表中的数据
  10. (openCV 十)ML_SVM