Unity内存分析与优化实践

前言

在移动端项目中,内存占用是一项非常重要的指标,一般都会被严格控制其大小,否则会导致内存占用过大而影响其他功能的使用。而在移动端Unity中,由于嵌入了Unity引擎,内存占用会一下子飙升,如果控制不好内存的增长,恐怕许多项目都不会允许Unity嵌入到移动端中,在这种时候,内存优化就变得尤为重要,接下来我就在实践中一步一步地对移动端Unity项目进行内存优化,通过工具分析和多角度优化内存,让大家可以清晰地看到内存优化的效果和掌握优化手段。

优化前分析

为了得到清晰的优化情况对比,我们先把优化前的App内存占用情况记录一下。一般情况下,查看Unity的内存占用可以使用Unity的Profile工具,但是该工具对内存占用的情况显示不是很详细,所以这里我们使用Memory Profile进行内存分析,Memory Profile的安装使用可以查看这个链接:Memory Profile官方文档,我们打开App,然后使用Memory Profile去抓一下快照,可以看到快照信息如下:
在这里插入图片描述

我们这里可以对整体的内存进行分析,这里大概说下每个各个部分的含义,便于我们理解内存占用构成:

Committed Memory Tracking Status

这个是设备提交的内存情况,可以用来看正在使用内存是多少,预留了多少内存

  • Total(总内存):表示Unity进程当前使用的总内存量。这包括所有已分配给Unity的内存,无论是实际使用中的内存还是预留的内存

  • In Use Memory(使用中内存):表示当前实际使用中的内存量。它反映了Unity正在使用的资源占用的内存大小,涵盖了纹理、模型、声音等加载的资源。

  • Reserved Memory(已预留内存):表示Unity为未来使用而预留的内存量。这些内存可能由于资源加载和运行时需求而保留,但尚未实际使用。

Memory Usage

在这里可以看到程序各部分占用的内存,可以方便我们针对性分析和解决内存占用问题

  • Managed Heap:是指运行在托管环境中,由.NET运行时(例如Unity使用的Mono或IL2CPP)管理的内存堆

  • Virtual Machine(IL2CPP):与IL2CPP虚拟机相关的内存占用

  • Graphics & Graphics Driver:图形渲染和图形驱动程序内存占用,一般和画面复杂度,分辨率,纹理,各种缓冲区,各种渲染技术特效等等相关

  • Audio:音频部分,和音频文件数据占用内存相关

  • Other Native Memory:这部分内存用于存储临时数据、中间计算结果、状态信息等

  • Profiler:用于分析性能的,这个一般无需理会,正式版本没这个

  • Executabe & DLLs:可执行文件和动态链接库的内存占用

从上面这些可以看到总览的内存占比,便于我们对整个程序的内存占用情况有比较全面的了解,接下来我们再看看更详细的内存占用情况,我们点击Tree Map菜单,可以看到Memory Usage Overview界面,下面列举了各个部分占用的情况:

在这里插入图片描述

从这些部分中就可以找出需要优化的点,我们点击较大的方块,比如Texture2d,就能看到下面详细的内存占用情况:

在这里插入图片描述

从图中可以看到,第一项占用21.3 MB,其他的占用会小一点,但是在移动端这些都是可以优化的点。第一项我们无法看出命名是什么,其实这里是中文命名的乱码,因此最好不要使用中文命名,否则不知道具体是什么导致的内存占用。我们点击第一项,可以看到以下界面:

请添加图片描述

可以从这里看到引用的物体,但是由于中文问题,导致依然不知道是哪个贴图,所以大家一定不要用中文的命名。这里每一部分都点进去看看,就能看到各项的内存占用,具体每部分的情况我就不贴出来了,接下来我们开始优化内存。

开始内存优化

贴图优化

贴图分辨率优化

一般贴图的内存占用是占Unity的内存大头的,因此我们首先需要对贴图进行优化,我们首先降低贴图的分辨率,这里为了快速就统一设置贴图最大分辨率为512了,实际工程中最好是为每个贴图设置最佳分辨率,设置最大分辨率的地方在:
在这里插入图片描述

我们看看优化效果:

在这里插入图片描述

可以看到,texture2d从74.7M降低到35.4MB,如果场景中高分辨率贴图多,那么这个优化将会更大。

去除透明通道和mipmap

一些贴图是不需要带上透明通道的,可以去除减小内存大小。还有就是mipmap,开启mipmap会增大大概1/3的内存大小。如果项目中没有远近景的切换,是用不到mipmap的,也可以关掉:

在这里插入图片描述

需要注意的是,这两项是否可以关闭需要根据项目实际情况而定,而且其实优化不是很大,以下是在测试项目中优化的效果(测试项目的贴图较少,优化程度很低):
在这里插入图片描述

只是从35.4M变成了34.1M而已,优化掉了1.3M。

其他关于贴图的优化技术

除了上述这两个操作外,还有一些其他的贴图优化技术,可以根据项目情况使用,比如利用Photoshop之类的工具对贴图进行专门的优化,保持效果的同时优化内存占用。也可以使用纹理合并,把多个小纹理合并为一个大的纹理图集,减少纹理的切换和内存开销。这些就看实际项目去做具体优化了。

Shader优化

shader的内存占用一般和shader的编写和加载有关,通常情况下不会占用特别大,除非shader编写特别复杂,变体特别多,这里就不详细每个步骤都讲述内存变化了,在执行多个操作后再统一看内存变化。

优化Always Included Shaders

Always Included Shaders在Unity设置的Graphics下面,是用于包含那些暂时没有引用但是在需要时动态加载的shader的,但是在这里的shader会无论用不用得到都会加载进去,不仅会增大内存,还会增加编译时间,所以尽量不要放在这里

优化Preloaded Shaders

"Always Included Shaders"和"Preload Shaders"是两种不同的Shader预加载选项,"Always Included Shaders"是一种将Shader直接包含在构建输出中的选项。这意味着不管场景中是否使用了这些Shader,它们都会被打包到构建中。而"Preload Shaders"是一种在运行时提前加载Shader的选项。这意味着只有在需要使用这些Shader时才会进行加载。这里需要填入的是一个shader变体集合,也要记得避免把集合中用不到的shader和其变体去掉,避免内存占用

优化Shader代码

在移动端尽量不要使用过于复杂的shader,可以尽量减少shader的pass,同时不要生成过多的变体,尽量做到简单高效。

共享Shader

如果多个如果多个对象使用相同的材质和Shader,可以考虑将它们合并为一个大的网格,以减少重复的Shader实例。这样可以节省内存并提高性能。

本次测试项目中使用到的shader不多也不复杂,通过上面这些技术,最终优化效果如下:

在这里插入图片描述

从一开始的38.1M降到37.2M,并且shader的数量也从54个降低到42个。

优化Mesh

  • 减少模型的面数可以显著降低内存占用

  • 将多个小模型合并为一个大的网格模型

  • 使用LOD(层次细节):根据物体与相机的距离,使用不同细节级别的模型,利用LOD功能可以降低模型的面数和纹理分辨率,以降低内存占用

  • 使用GPU Instancing:对于需要大量重复实例的模型,使用GPU Instancing技术可以共享材质和缓冲区数据,以减少内存开销。

  • 尽量避免使用骨骼动画:骨骼动画(Skinned Mesh Animation)通常消耗比较多的内存。如果没有必要,尽量使用其他动画技术(如顶点动画、物理动画),或者尝试使用成批处理(Batching)等技术来减少动画对象的数量。

  • 使用顶点压缩:Unity提供了顶点压缩选项,可以减小存储每个顶点所需的内存。您可以在导入模型时选择适当的压缩选项,例如使用Half精度来减小顶点的内存消耗

对于模型Mesh部分,优化大头在于模型的制作简化这里,尽量使用低模,模型细节用别的技术模拟实现,而不要增加过多面数,测试项目中用到的模型已经是最简,这里就基本没什么优化空间了。

降低屏幕分辨率

降低屏幕分辨率也可以减少整体的内存占用,例如从19201080降低到1280720,可以看到效果:

在这里插入图片描述

可以看到,RenderTexture大幅度降低,优化幅度非常大,因此在移动端,分辨率这一项设置变得非常重要,尽量使用较低分辨率。

优化效果内存占用

一般项目中还会用到一些类似于后处理,抗锯齿,阴影,灯光数量等方面的效果,虽然视觉上确实会增加不少,但是内存也跟着增加上来了,所以尽量也要减少这些方面的使用。在测试项目中,后处理使用到了

  • Post Process全局后处理

  • TTA抗锯齿

  • Bloom

  • 高质量阴影

  • lighting count为6

针对上面这些进行优化:

  • 去掉Post Process全局后处理

  • TTA抗锯齿换成Unity自带的MSAA抗锯齿,设置为2x

  • Bloom使用Shader实现

  • 降低阴影质量

  • lighting count降低为4

最终得到的画面效果其实差别不会特别大,最终内存优化如下:

在这里插入图片描述

可以看到,各项占用内存再次大幅度降低,特别是RenderTexture,从29.7M降到了9.7M。

其他内存优化

一般情况下,内存占用最大的都是资源和效果,但还有一些其他的方面需要注意的,虽然本次测试项目中这些方面占比不大,但是也在这里列出来,在项目中也要注意这些方面的优化:

  • 动画的优化:一般项目使用动画都会使用动画控制器进行播放,但如果动画控制器里设置了较多的动画,则会占用不少内存。如果可以,使用动态加载动画的方式,用不到的动画及时卸载,避免内存占用。除此之外,动画数据的也不要太过于复杂,记得去除重复帧,减少关键帧,减少动画节点,这样会使动画变得更小,占用内存也会更小

  • 音频优化:音频部分也会占用不少的内存,可以强制使用单声道,压缩音频,重采样等方式减少内存占用

  • 代码优化:代码逻辑中也要注意内存的占用,不要滥用单例和静态类静态属性等。

优化结果总结

通过查看各个步骤的Memory Profile的Objects and Allocations的Total Size数据,可以得到较为准确的内存占用数据,最后得出的数据如下:

未优化贴图优化后Shader优化后降低屏幕分辨率后效果内存优化后
230.0M189.4M188.5M123.2M77.8M

可以看到,即使是一个比较简单的项目,经过一系列的内存优化后,也能达到一个非常不错的效果,但无论如何,在内存优化的过程中也不能一味的放弃质量,因此在项目里实际优化需要因情况而定,选择最适合项目的方式,尽量保持一个性能和效果都相对比较不错的情况。

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Nbin_Newby

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值