技术分享连载(九十)

技术分享连载(九十)

本期聚集话题:Dalvik Heap 内存过高、Unity 5和Unity 2017版本下帧率降低、如何处理Animator.Initialize警告...


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

UWA QQ群:793972859
UWA 问答社区:answer.uwa4d.com


内存

Q1:我们发现刚进入游戏,Dalvik Heap的内存很高,导致PSS比较高,切到后台,再切回游戏,Dalvik Heap内存减少非常多。然后我尝试使用网上说的Android调用GC的方式,System.GC,结合runFinalization。调用Runtime.getRuntime().gc(),都无法有效减少,不知道这块是否有办法有效调用一次?

我们查到原因了,是因为我们在Android层写了一个splash,但这个splash是png的,分辨率是1920x1080,我们之前是
int splash_bg = getResources().getIdentifier(bgName, “drawable”, getPackageName());
m_BgView.setBackgroundResource(splash_bg);

这张图片在HideSplash会被处于游离状态,要等Java的GC调用后,才会回收,但实际图片按道理内存也不该涨100MB左右,我们用测试工程只有Splash和SplashVideo,发现内存并不会增长那么多,代码一模一样。后面只能解释,可能JVM后某种内存分配算法造成的,当本来比较低的情况,分配会比较少,当到达一定数量级,再分配,就会分配更大一块内存(对Android底层机制不熟)

后面我们改为先从getResources里获得BITMAP,然后给ImageView,再HideSplash时候,调用Bitmap的手动释放方法。

该问题来自UWA问答社区,感谢题主在解决后将其方法分享公开,如您对该问题仍有疑问,可以转至社区进行进一步交流。
https://answer.uwa4d.com/question/5a2a04c27030070236a983f5


制作

Q2:我有一个MeshRenderer,它拥有两个材质,现在我想给其设置一个不同的MaterialPropertyBlocks,但据我所知,目前还没有能实现这样的办法,因为当我从Renderer中得到MaterialPropertyBlock后,我是不能指定它还能应用于某个材质了是吧?不知道大家有没有好的解决方法呢?

是的,MaterialPropertyBlocks是以MeshRenderer为单位的,而不是以Material为单位的。只能建议题主对Mesh进行拆分,确保每个Renderer上只挂一个Material。

该问题来自UWA问答社区,如您对该问题仍有疑问,可以转至社区进行进一步交流。
https://answer.uwa4d.com/question/5a263f54d99fdb2b3c628873


性能

Q3:最近项目从Unity 4 升级到Unity 5或Unity 2017时,在中低端Android机上,帧率降了10多帧,用Adreno Profiler上查了是GPU Bound。

我们游戏对帧率要求比较高, 游戏的时候必须满帧运行, 所以这个问题很明显。经过折腾,最后查出来是Unity 5 之后, 默认开启了Blit, 分辨率越高,GPU压力越大。 尤其在中低端机上,我用的是Adreno 405测试的, Unity 4能满帧, 但Unity 5或者Unity 2017最高才45左右, 简直不能忍。幸运的是,Unity 2017.2,官方终于开放了设置能禁止Blit. 但是Unity 5就没这个运气了, 根据官方的消息,他们暂时还没有计划把这个引入Unity 5.6,
具体帖子可见:https://forum.unity.com/threads/big-performance-issue-with-unity5-on-android.338847

在发现和解决问题的过程中,钱康来同学提供了不少帮助,在此感谢!开这个问题也是让大家知道下,免得像我当初摸石头过河,花太多时间折腾。

该问题来自UWA问答社区,感谢题主的无私分享,建议使用Unity 2017 或者Unity 5 版本的开发者密切注意!如您对该问题仍有疑问,可以转至社区进行进一步交流。
https://answer.uwa4d.com/question/5a282669a670486845f8a03d


内存

Q4:这个[Triggers RebuildInternalState]是隐藏物体就一定会触发的吗?我看Profiler里最后一列都有提示Warning,感觉挺重要的一个错误。这个要怎么去避免呢,是否会导致Animator.Initialize耗时又变得很明显(在之前有做过缓存的情况下)。
请输入图片描述

这个是含有Animation组件的GameObject被Deactive时的引擎Warning,在很多情况下确实会造成较高的CPU耗时。对此,建议题主尝试在GameObject不再需要使用时,直接将其移出屏幕外,并将其挂载的Component进行Disable,而非将其GameObject进行Deactive,这样可以RebuildInternalState的发生。

该问题来自UWA问答社区,如您对该问题仍有疑问,可以转至社区进行进一步交流。
https://answer.uwa4d.com/question/5a2a62cdff95f1253a1b365e


Unreal 4 渲染

Q5:你好 我看了UWA关于Unreal全局光照的那篇文章,有几点疑问想问下:
1、Unity的Lightmap烘焙时,为什么不能从Normal map获取Normal信息呢?我看Unreal的Lightmass也是烘焙出两张图,一张方向一张颜色。它的颜色可以受NormalMap的影响吗?
2、Unreal的一个场景多张Lightmap,例如白天到晚上,渐变是怎么融合的呢?

1、Lightmap中的Directional信息是指烘焙光照的方向信息。在Lightmap中一张是记录光照的Intensity,一张是记录Direcitonal,这个Directional是用来参与Shading中方向相关计算的,例如:高光计算、与normal计算等。如果是纯Dffuse材质也不用Normalmap,这个Directional信息可以去掉,减少存储和计算量。通常在材质中看到的Normalmap指的是Mesh的Normal与Lightmap中记录的Directional并不是同一个值。

2、Unreal中的Precomputed Lighting Scenarios是保存了多套Lightmap以及光照设置,只能做到配合光照进行Lightmap切换,融合现在貌似还做不到。


Q5:烘焙的时候光照的Intensity考虑Normal就类似beast那样,Lightmass烘焙的时候可以提供Normalmap吗?

我是这样理解的:Unity烘焙的时候用了辐射度,也就是先把模型分成块,然后计算快与块之间的反射,不会使用Normalmap。Normalmap提供的是细节的信息,全局光照中间接光的计算结果相对比较低频,比较平滑,加入高频的信息不一定会有好的效果。Unreal 4的lightmass可以有一个选项设置Static类型的光源在烘焙的时候使用normal map,其设在project settings->engine rendering->lighting中。

该问题来自UWA问答社区,如您对该问题仍有疑问,可以转至社区进行进一步交流。
https://answer.uwa4d.com/question/5a28b0592de8d7470d08f62e

今天的分享就到这里。当然,生有涯而知无涯。在漫漫的开发周期中,您看到的这些问题也许都只是冰山一角,我们早已在UWA问答网站(answer.uwa4d.com)上准备了更多的技术话题等你一起来探索和分享。欢迎热爱进步的你加入,也许你的方法恰能解别人的燃眉之急;而他山之“石”,也能攻你之“玉”。
官网:www.uwa4d.com
官方技术博客:blog.uwa4d.com
官方问答社区:answer.uwa4d.com
官方技术QQ群:793972859(仅限技术交流)