关于Unity UI的动静图集分离,你需要了解这些!

关于Unity UI的动静图集分离,你需要了解这些!

本期我们聚集了这些话题:UI 图集静态分离、Unity烘焙问题、Unity渲染异常、Animation.RebuildInternalState......(UWA一下,你就知道~)


这是第101篇UWA技术知识分享的推送!(此处应有掌声)随着大家在UWA平台上的发言愈加活跃,我们也源源不断地收到了许多技术大咖的热心回复和真知灼见。

UWA 问答社区:answer.uwa4d.com
UWA QQ群:793972859(仅限技术交流)


UI 管理

Q1:对于Unity的静态图集和动态图集分离,我有些疑问。我们UI制作方法如下:

  • Prefab (UIHero)
  • Prefab的静态图集 (UIHeroAtlas)
  • Prefab上可能的动态图集 (UIHeroIcon) 如头像

生成的Bundle:

  • Prefab一个bundle,它包含了静态的图片
  • 动态图集一个Bundle

后来,为了能动态合批减少几个DrawCall,可能静态图集上有2-3张图片,在动态图片的上面当一个小边框背景。然后美术想把它放到动态图集,这样图片重叠时,它和动态图集的图也会是一个DrawCall。

我们的问题是:在使用AB的方式加载这个UI-prefab时,会不会加载整个动态的图集(UIHeroIcon)呢?还是说不会加载整个UIHeroIcon,只是把这两个静态图加载,动态UIHeroIcon照样不会加载?这种方式是否会造成热更新UIHeroIcon动态图集后,导致UIHero-prefab无法加载这两个静态图片的情况?那么我该如何取舍?

1.会不会加载取决于你,Unity只是给出依赖列表,是否加载自行控制。
2.不会加载整个UIHeroIcon。
3.这里差不了几个DrawCall。而前景可能有很多种,美术的方案不一定通用,以后可能会拆回来。我的理解是,是静态图集中有2个Sprite A和B,然后在动态图集中也复制一份A和B。重叠时,如果UI深度不同,不一定可以合并。资源结构为重,不然之后维护会很麻烦。

感谢UWA问答社区 @史云柯 提供了回答

UWA补充:补充下史云柯回答中的第三点,建议评估下DrawCall能节省多少。举个例子,如果是个10人MOBA,那么在团战过程中10个Icon可能是叠在一起的,由于图集穿插就有可能增加到20个DrawCall,对于中低端设备节省20个DrawCall的话,性价比还是可以的。如果最差情况也就10个不到,那么确实性价比不高了。

此问答来自于UWA 问答社区,欢迎大家转至社区进行进一步交流:
https://answer.uwa4d.com/question/5a94dd200b827e2c0bfdd022


渲染

Q2:请问各位Unity5.3烘焙得到的LightingData.asset、Lightmap-0_comp_dir.exr、Lightmap-0_comp_light.exr各有什么作用呢?打包和加载的时候实际上是用了哪一个文件,还是全都需要?

UWA:LightingData.asset的介绍可以看这两个文档:
https://docs.unity3d.com/Manual/LightmapSnapshot.html
https://answer.uwa4d.com/question/5a4f4367e041ef3c50c9ce64

简单说,这里面存的就是场景中各个受Lightmap影响的物件的相关信息,Editor下这个文件可能会很大;但真机上,在不使用precomputed gi的情况下这部分的数据打包到手机上应该是很小的(毕竟对于一个物体来说,主要的Lightmap信息就是lightmapIndex和lightmapScaleOffset)。

另外,这部分信息是和场景文件绑定的,不能单独管理。所以默认情况下,Lightmap只能随场景一起加载。如果需要动态加载lightmap,可以参考这篇文章:http://www.xuanyusong.com/archives/3807;而后面两个.exr文件就是储存光照信息的纹理,_dir是光的方向信息,_light是光强信息(最简单的模式下只需要这一张)。这些文件是运行时需要的,不过exr是支持HDR的格式,在手机上会默认转成其他格式的,大小与exr是不同的。

该回答由UWA提供,欢迎大家转至社区进行进一步交流:
https://answer.uwa4d.com/question/5a9a69720b827e2c0bfdd0a7


动画系统

Q3:Camera.Render里面Animation.RebuildInternalState耗时较多,调用比较频繁,这个主要是哪些情况会调用呢?

UWA:之所以出现这一项,主要可以说明一下两点:
(1)题主项目用的是Animation老版本动画系统;
(2)对含有Animation组件的GameObject进行了大量频繁的Active或者Instantiate操作,一般这种情况比较常见于特效、UI HUD、角色/怪物等。
对此,研发团队可以通过上述两点查看是否如此。

该问答由UWA提供,欢迎大家转至社区进行进一步交流:
https://answer.uwa4d.com/question/5a953c61d35eb22c10a0a29d


UI 管理

Q4:在UI优化中,是每张图集的内存占用对效能影响显著,还是图集数量(draw call)显著?比如8 张 1024 图集 和 2 张 2048 图集哪个更优?

其实没有统一的标准说8 张 1024 图集 和 2 张 2048 图集那个会哪个更优,比如如果4张1024的贴图会一直在同一个UI中出现,同时加载同时渲染,那通常合并成一张2048的图集会更合理,而如果这4张1024的贴图在只在很少情况下才会同时出现1-2张,那合并成2048的贴图就是内存浪费。

这种极端情况的处理方式相信题主可以想到,所以这里是一个根据具体需求的选择,而没有哪个更好,具体的选择标准还要看项目是内存更加吃紧还是UI的DrawCall更加吃紧。

个人建议是,对于可能会常驻内存的,通用的那些资源,可以给予更高的图集大小的限定,比如允许最大2048甚至4096一张;而对于单个游戏功能内部的独有图集,我们是建议UI控制在1024以内,如果使用量到了3张1024的级别,才允许使用2048的贴图尺寸。毕竟如果分配合理,多一张贴图理论上可以做到只多1个DrawCall,而2张1024如果要用2048的贴图,空白的地方会比较多,或者不合理的合并,会导致内存占用比较浪费。

感谢UWA问答社区 @贾伟昊 提供了回答,欢迎大家转至社区进行进一步交流:

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


渲染

Q5:Unity 5.5.2f1版本的项目中有少量模型在使用Cull Back的Shader时,渲染异常。我新建Unlit Shader,添加Cull Back的tag;用该Shader渲染角色的时候,发现如下图问题:
请输入图片描述
将Cull Back改为Cull Off 、Cull Front时,效果正常。
所以,我怀疑该模型的正反面反了;但是据我们美术说,3dmax中网格的正反面是由法线方向决定的,而法线方向是正确的,所以不是模型资源的问题。
所以修改Shader,将法线作为片段着色器的输出后,得到下图结果:

请输入图片描述
看上面这图,法线好像也没啥问题,那问题原因在哪呢?相关的例子我已经提交至UWA问答官网。

UWA:三角形面片的front和back不是由法线决定的,是由三角形的三个顶点投影到屏幕上的顺序决定。默认情况下gles是以逆时针方向的面为front,顺时针为back。虽然上面法线方向是对的,但是它跟face culling没有关系。从上面结果看应该是美术输出时候三角形面片顶点顺序弄反了,让他们改过来应该就行了。

关于face culling可以参考这两个函数:
https://www.khronos.org/registry/OpenGL-Refpages/es2.0/xhtml/glCullFace.xml
https://www.khronos.org/registry/OpenGL-Refpages/es2.0/xhtml/glFrontFace.xml

其实,face culling和法线反了是两种相像。
请输入图片描述

  1. face culling的,你在那个Shader里加一句Cull Off,如果显示正常如上图,就说明面反了。
  2. 法线反了,选中模型时在右下角的预览(或直接拖到场景里打上光),你会看到黑乎乎的,为什么呢。dot(lightdir,normal),因为法线反了,这个值基本为0,diffuse 乘上这个值也会为0。

感谢UWA问答社区 @Kent 提供了回答

欢迎大家转至社区进行进一步交流:
https://answer.uwa4d.com/question/5a97763fd35eb22c10a0a2c3


今天的分享就到这里。当然,生有涯而知无涯。在漫漫的开发周期中,您看到的这些问答也许都只是冰山一角,像这样实用的知识点在UWA问答平台(answer.uwa4d.com)上还有一打!UWA欢迎热爱进步的你加入,也许你的方法恰能解别人的燃眉之急;而他山之“石”,也能攻你之“玉”。