Unity技术分享89-资源卸载API、内存变化、数值

我们将从日常技术交流中精选若干个开发相关的问题,建议阅读时间15分钟,认真读完必有收获。如果您有任何独到的见解或者发现也欢迎联系我们,一起探讨。

内存

Q1:我写了一个用例加载AssetBundle,并将多个特效Prefab实例化到场景中。连续运行了多次用例并把添加的特效对象都删除,而且切换了场景,我看到Profiler中的内存变化如下图所示:

我想咨询下:

1.Profiler里的Reserverd Unity内存比Used Unity内存高出很多是正常的吗?

2.如果正常的话,有办法可以回收Reserverd Unity内存吗?

3.Reserverd Unity内存在运行完多次上述的用例后稳定在400MB,再运行一次用例可以上涨到450MB,虽然后面会回落到400MB。这样的表现也是正常的吗?

题主这个数据是在Editor中做测试的结果吗?Reserverd比Used高出这么多确实不太合理;但如果是Editor中,那么Unity其实会做很多辅助操作,这些也确实是会占用内存的。所以,建议在真机中测试看看,看看这个差距是否会下来。但如果是在真机中,那么这个差距确实过高了,不太合理。

Reserverd Unity的内存是引擎自身管理的,一般会在后续不使用时自己降下来。

这种升高和回落是正常的,但至于是否应该这么高,请见1中的回答。

该问题来自UWA问答社区,如您对该问题仍有疑问,可以转至社区进行进一步交流。

https://answer.uwa4d.com/question/5a1fde25bd7d86f726903207

内存

Q2:我想咨询下,Resources.UnloadUnusedAssets() 在卸载旧场景后加载新场景前调用好,还是在加载新场景后调用比较好呢?如果考虑内存峰值的话,我觉得是前者好,但是在UWA上看到有些文章说是加载场景后调用,所以想深入学习下。

如果题主是通过LoadLevel(Async)类似的方式来加载场景的话,那么Unity自身会在底层执行一次类似Resources.UnloadUnusedAssets的操作。所以,这时如果手动调用Resources.UnloadUnusedAssets操作,时间间隔很短,其实这个是有些重复的。因此,我们才建议在新场景加载后再调用一次。

但如果题主使用LoadLevelAdditive或其他类似的API来切换场景的话,那么Unity是不会调用Resources.UnloadUnusedAssets的,这时你再旧场景卸载后调用,其实也是很不错的选择。

该问题来自UWA问答社区,如您对该问题仍有疑问,可以转至社区进行进一步交流。

https://answer.uwa4d.com/question/5a1fc7dbbd7d86f726903206

渲染

Q3:是否可以认为Shader里 Blend Off和Blend One Zero是完全等价的?我在Unity的Standard Shader里看到它的混合是使用形如Blend [_SrcBlend] [_DstBlend]来动态控制,并且注意到其在StandardShaderGUI.cs里设置Opaque时就是设置的 Blend One Zero,那么是否可以认为在Shader里写Blend One Zero的话,和Blend Off是等价的?Unity会自动改变blendstate从而避免从destbuffer读取数据?

我们在Unity 2017.1上测试了一下,发现实际上在Android平台的GLES调用中,Unity的Standard Shader的Opaque模式是在disable blend的状态下渲染的,实验如下:

设备:红米2。渲染场景是两个Standard Shader Opaque模式物体(Sphere和Cube),中间有一个Unlit Transparent的Quad:

通过Android工具查看GLES API调用发现,每一帧渲染Cube和Sphere的时候Blend都是关闭状态(上一帧结束时关掉),然后在渲染Unlit Transparent的Quad时打开:

其中,36个顶点的DC是渲染Cube,2304个顶点的DC是渲染Sphere,6个顶点的 DC是渲染quad。所以看起来Standard Shader的Opaque模式应该是glDisable(GL_BLEND)的状态下渲染的。

该问题来自UWA问答社区,如您对该问题仍有疑问,可以转至社区进行进一步交流。

https://answer.uwa4d.com/question/5a1a8e710aef30913881b489

内存

Q4:在游戏每次打完副本回到主界面后,内存数据总是不太一致,其中通过Unity Profiler我观察到ManagedHeap.ReservedUnuseSize和ManagedHeap.UseSize的数值一直在变化,请问这个变化是否是合理的?

ReservedUnuseSize和ManagedHeap.UseSize一直在变化是正常的,它们都属于Mono内存,前者是当前Mono内存中没有使用的,后者是正在使用的。一般游戏中,Mono堆内存是会经常由代码来进行分配的,所以这两个值一直在变化,也是很正常的情况。

这里建议题主密切关注以下两点:

(1)Mono的总堆内存是否一直在升高

下图是UWA性能测评报告中的Mono堆内存走势图,其中的紫色线条即为项目运行时的ManagedHeap.UseSize,而黄色线条为ReservedUnuseSize,这两者都是在变化的,但最需要关心的是蓝色线条Reserved Mono,这条线条如果持续往上走,那么就说明项目中是很可能出现了内存泄露问题,需要研发团队彻查,建议通过Mono详细堆内存分析来进行修复。

(2)具体的堆内存分配是否合理

ManagedHeap.UseSize或者Mono总内存的上升都是由于代码的堆内存产生的,所以查看代码堆内存分配是否合理,避免不必要的堆内存分配是非常重要的,类似于下图。

建议题主参考以下两篇文章:

用正确的方式,三天搞定Mono堆内存泄漏!

Unity游戏的代码堆内存优化

该问题来自UWA问答社区,如您对该问题仍有疑问,可以转至社区进行进一步交流。

https://answer.uwa4d.com/question/5a24efc0355737361cc410c9

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180329A0G75D00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券