技术分享连载(三)

技术分享连载(三)

【技术小札】是UWA推出的技术交流栏目,我们会将开发团队中反馈的常见问题加以总结并梳理在此,以供大家参考。同时如果你也是个热爱分享、愿与大家抱团进步的程序员,欢迎加入UWA的QQ群(793972859),与我们奇文分享,疑义相析。


内存管理

Q1:如图,在Editor中查看Profiler里的内存详细信息,发现Used Total中有个“Unity”,请问是什么意思?为什么会特别大?

UWA Tech Doc

在Editor中运行时,“Unity”大是正常的,因为在Editor中运行项目时,引擎包含了所有的资源占用的内存(除了部分纹理和Mesh是在GFX中),同时自身会进行很多的辅助操作来记录各种游戏运行信息。一般来说,在查看游戏运行时的真实消耗内存,我们均是推荐直接在发布游戏上通过Profiler进行查看,在Editor中运行游戏所看到的内存是要大很多的。


内存管理

Q2: 在进行内存优化时,Unity Profiler给出的数据和Android系统(adb dumpsys meminfo,已经考虑memtrack的影响 )的数据差距较大(已经分析了Profiler自身的内存占用),如何分析这部分差异,比如包括对显存消耗进行准确统计,OS消耗的统计等等?

内存差异较大是正常的,一般来说,Profiler统计的内存较为一致,而Android系统通过ADB反馈的PSS、Private Dirty等值则是差别很大。这主要是因为芯片和OS的不同而导致。具体的Android内存,建议直接查看Google Android OS的相关文档。
Unity Profiler反馈的则是引擎的真实物理使用内存,一般我们都建议通过Profiler来查看内存是否存在冗余、泄露等问题。


资源管理

Q3:iOS上PVRTC不支持NPOT的贴图压缩,在Android上可以用ETC2,但在iOS上不能压缩,内存消耗大。请问在iOS上有没有好的处理方案?

ETC2仅能在支持OpenGL ES3.0的手机上进行使用,请研发团队在使用前谨慎考察支持ES3.0的手机在国内的覆盖范围。
PVRTC不支持NPOT的贴图压缩,这是Apple规定的,上层应用无权对此更改。我们仅能建议将纹理尽可能做成POT形式,否则只能接受内存较大的开销,没有其他更好的办法。


资源加载

Q4:怎样动态加载Navmesh?

目前Navmesh不支持动态加载,只能随场景一起加载, 因此可以考虑将带有Navmesh的场景打包成AssetBundle,然后使用LoadLevel加载AssetBundle中的场景。
Navmesh的动态加载已经在Unity的Roadmap中。而当前,Navmesh是和场景绑定的,也就是说目前只能通过LoadLevel(不支持LoadLevelAdditive的加载方式)来加载场景的同时,自动加载对应的Navmesh数据。替代方案是:将多个“场景Prefab”的Navmesh 合并到同一个场景中烘焙好(互不重叠),然后再将这些“场景Prefab”分离到各个单独的场景中去;在运行阶段,Navmesh随着第一个场景一次性加载,而对于其他的场景物件,再通过LoadLevelAdditive来加载对应的场景即可。缺点是为了使场景物件对齐Navmesh,在场景制作时就不能出现坐标上的重叠,因此仅供参考。
在Unity 5.x下,Lightmap的动态加载,需要通过脚本将烘焙时每个物件的Lightmapindex和Lightmapscaleoffset记录下,并在运行时动态加载后设置回去的方式来实现。因为目前Lightmapindex和Lightmapscaleoffset信息是和场景绑定在一起,储存在Lightmapsnap.assets 中,发布时也是放在场景信息中,因此不会记录在Prefab 上。


图形渲染

Q5:当关闭预渲染GI时会出现IndirectResolution,这个参数有什么用,为什么调大了以后会大大增加渲染时间,但是烘培出来却没有什么效果。

该值主要控制的是GI的烘焙密度,数值越大,表示每个单位距离内的Texel越多,即烘焙得越精致,自然烘焙的时间也越长。
该值并非越大越好,场景越小建议该值越低。该值为1时,对于多数场景,其烘焙效果已经足够了,升高该值,其效果也不会有明显提升。