Unity性能优化与分析--内存

1 Reserved Unity内存

1.1 常见的共通性问题

这一部分提到的问题没有特定性,不仅仅出现在一种资源内存中。所以,为了避免赘述,此处统一予以讨论。

1.1.1 序列化信息内存占用

Unity引擎的序列化信息种类繁多,其中最为常见且内存占用较大的为SerializedFile。该序列化信息的内存分配主要是项目通过特定API(WWW.LoadFromCacheOrDownload、CreateFromfile等)加载AssetBundle文件所致。

1.1.2 资源内存占用

主要包括Mesh、AnimationClip、RenderTexture等资源。对于未开启“Read/Write Enable选项的Mesh资源,其内存占用是统计在GFX内存中供GPU使用的,但开启该选项后,网格数据会在ReservedUnity中保留一份,便于项目在运行时对Mesh数据进行实时的编辑和修改。同时,如果研发团队同样开启了纹理资源的“Read/Write Enable” 选项(默认情况下为关闭),则纹理资源同样会在Reserved Unity中保留一份,进而造成其更大的内存占用。

1.1.3 疑似冗余现象

在UWA GOT Online Resource模式报告的具体资源列表(下文简称资源列表)中,我们常能看到某一项资源的数量峰值大于1且被标红。数量峰值同样是资源使用中非常重要的一项指标。所谓“数量峰值”,是指同一资源在同一帧中出现的最大数量。理论上,数量峰值这一参数不应大于1,当数量峰值大于1时,列表中会将其标红,我们称之为疑似冗余资源。

一般情况下,出现这种问题是由AssetBundle资源加载导致的,即在制作AssetBundle文件时,部分共享资源(比如Texture、Mesh等)被同时打入到多份不同的AssetBundle文件中但没有进行依赖打包,从而当加载这些AssetBundle时,内存中出现了多份同样的资源,即资源冗余,建议对其进行严格的检测和完善。

针对排查出的疑似冗余现象,可以使用UWA在线AssetBundle检测工具排査是否确实存在AssetBundle冗余的问题,尽量减少AssetBundle的冗余。建议根据冗余资源的内存大小来决定对冗余问题的优化优先级。

值得一提的是,所谓 “疑似冗余资源”,是指在检测过程中,我们尝试搜索项目运行时的冗余资源并将其反馈给用户。但是,我们并无法保证该项检测的100%正确性。这是因为,我们判断的标准是根据资源的名称、内存占用等属性(因资源类型不同可能有格式、Read/rite、时长等属性,以报告资源列表中呈现的属性为准)而定,当两个资源的名称、内存占用等属性均一致时,我们认为这两个资源可能为同一资源,即其中一个为“冗余” 资源。但项目中确实也存在资源不同但各项属性都相同的情况。因此,我们将通过以上规则提取出的资源归为“疑似冗余资源”。所以,是否确实为冗余资源,还需要结合项目实情和在线AssetBundle检测报告才能下结论

1.1.4 未命名资源

在资源列表中,有时发现存在资源名称为N/A的资源。一般来说名为N/A的资源都是在代码中new出来但是没有予以命名的。建议通过.name方法对这些资源进行命名,方便资源统计和管理,尤其是其中冗余比较严重的或者个别内存占用非常大的N/A资源应予以关注和严格排查。

1.1.5 常驻资源内存占用大

在资源列表中,有时结合资源的生命周期曲线发现,一部分本身内存占用较大的资源在被加载进内存后,驻留在内存中,直到测试流程结束都没有被卸载,可能造成越到游戏后期资源内存占用越大、峰值越高。建议排查这些资源是否有常驻在内存中的必要。如果不再需要被使用,则应检查为什么场景切换时没有卸载:对于持续时间久的单场景中持续驻留的资源,则可以考虑手动卸载。

1.2 纹理资源

1.2.1 纹理格式

纹理格式设置不合理通常是造成纹理资源占据较大内存的主要原因之一。

即便是对于很多已经建立过美术资源标准并统一修改过纹理格式的项目而言,仍然很容易统计到存在大量的RGBA32、ARGB32、RGBA Half、RGB24等格式的纹理资源。

这些格式的纹理不但内存占用较大,还会导致游戏包体较大、加载这些资源的耗时较高、纹理带宽较高等等问题。

出现这类问题的主要原因:

  • 美术命名不规范导致没有被回调函数修改,或者是代码中创建的资源没有设置其纹理格式:

  • 硬件或纹理资源本身不支持目标格式纹理,导致被解析为未压缩格式的纹理。

推荐的纹理格式:

  • 对 iOS 和 Android 都使用自适应可伸缩纹理压缩 (ATSC)。绝大多数开发目标最低规格设备游戏都支持 ATSC 压缩。

  • 适用于面向 A7 设备或更低规格的 iOS 游戏(例如 iPhone 5、5S 等)— 使用 PVRTC

  • 适用于面向 2016 之前的设备的 Android 游戏 — 使用 ETC2(Ericsson 纹理压缩)

如果压缩格式(如 PVRTC 和 ETC)的质量不够高,并且目标平台不完全支持 ASTC,请尝试采用 16 位纹理而不是 32 位纹理。

请参阅手册了解有关各平台的推荐纹理压缩格式的更多信息。

1.2.2 分辨率
  • 不能让美术人员通过增加纹理大小的方式增加细节,可以选择细节贴图DetailMap或增加高反差保留的方式。

  • 对于移动平台来说, 其中最为需要关注的是占据较大分辨率(一般为>1024)的纹理。

  • 在不降低视觉效果的情况下尽量减小贴图大小,最好的方式是纹理映射的每一个纹素的大小正好符合屏幕上显示像素的大小,如果纹理小了会造成欠采样,纹理显示模糊,如果纹理大了会造成过采样,纹理显示噪点。 这一点做到完美平衡很难保障

  • 可以充分利用Unity编辑器下SceneView->DrawMode->Mipmap来查看在游戏摄像机视角下哪些纹理过采样,哪些纹理欠采样,进而来调整纹理大小。

在不同档位的机型上使用不同分辨率大小的纹理资源是非常实用且易操作的分级策略。这一点即便对于图集纹理也同样适用,特别地,Unity针对SpriteAltas提供了Variant功能,可以快捷的复制一份原图集并根据Scale参数降低该变体图集的分辨率,以供较低的分级使用。

1.2.3 禁用Read/Write Enabled

如果启用,此选项在 CPU 和 GPU 可寻址内存中都会创建副本,纹理会占用双倍内存。大多数情况下,应保持此选项为禁用状态。

不需要在运行时进行修改的资源是不需要开启Read/rite Enabled选项的,开发者应排查并关闭不必要的设置从而降低内存开销。

如果要在运行时生成纹理,请通过 Texture2D.Apply 强制执行,并且传入设置为 truemakeNoLongerReadable

UWA GOT Online Resource模式报告资源列表或是本地资源检测报告

1.2.4 Mipmap

逐级减低分辨率来保存纹理副本。相当于生成了纹理LOD,渲染纹理时,将根据像素在屏幕中占据的纹理空间大小选择合适的Mipmap级别进行采样。

优点:

  • GPU不需要在远距离上对对象进行全分辨率纹理采样,因此可以提高纹理采样性能。

  • 解决了远距离下的过采样导致的噪点问题,提高的纹理渲染质量。

缺点:

  • 当一张纹理开启Mipmap时,它的内存占用会上升为原始数据的1.33倍。

参数介绍:

  • Border Mip Maps 默认不开启,只有当纹理的是Light Cookies类型时,开启此选项来避免colors bleeding现象导致颜色渗透到较低级别的Mip Level纹理边缘上

  • MipMap Filtering

    • Box 最简单,随尺寸减小,Mipmap纹理变得平滑模糊

    • Kaiser 避免平滑模糊的锐化过滤算法。

  • Mip Maps Preserve Coverage 只有需要纹理在开启mipmap后也需要做Alpha Coverage时开启。默认不开启。

  • Fadeout MipMaps 纹理Mipmap随Mip层级淡化为灰色,一般不开启,只有在雾效较大时开启不影响视觉效果。

注意事项:

  • 对于在屏幕上大小保持不变的纹理(如 2D 精灵和 UI 图形)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值