UWA

每天一点UWA:第九周

Posted by 蔡华的博客 on September 25, 2017

AssetBundle

关于AssetBundle依赖的问题

  • 如果Panel A和Panel B,它们均依赖一个共享Atlas C。如果在加载完AtlasC后卸载它所在的AssetBundle,再创建A和B,此时会失败。因为他们的依赖关系在AssetBundle上。

请教一下,SerializedFile的卸载规则是什么呢?会跟随这AssetBundle一起卸载么?

  • 绝大部分的SerializedFile均由AssetBundle产生,当AssetBundle被卸载时,与其对应的SerializedFile也将销毁。

WWW.LoadFromCacheOrDownload只是在内存中有个引用,没有实际加载资源,调用WWW.assetbundle后也是么? 那么依赖此AssetBundle的资源加载的时候,会自动触发此AssetBundle从磁盘加载对应的引用资源么?

  • 在调用WWW.assetBundle之后,内存中也只是存在较小的SerializedFile(不包含资源数据)。“那么依赖此AB的资源加载的时候”确实会触发该AssetBundle通过磁盘IO加载资源。

Build

细谈Optimize Mesh Data选项

  • 第五周的时候说过Optimize Mesh Data选项的问题,但是只是说了和模型上的optimize的区别和一些问题,下面详细说说这个选项,以下内容来自这里
  • Unity 在底层默认希望为你做尽可能多的优化,降低使用门槛,比如 BuildSetting 中的 Optimize Mesh Data 选项就是一个典型的例子。这个选项到底有什么用呢?文档描述为:

Optimize Mesh Data Remove any data from meshes that is not required by the material applied to them (tangents, normals, colors, UV).

  • 即是说:如果开启了此选项,将会在 Build 过程中根据场景中 Mesh 所使用的材质(或者说 shader)进行静态分析,来去掉 Mesh 中“无用”的数据(材质不使用的数据),比如:切线,发现,定点色,多余的 uv 等,以此减少数据量和最终构建的游戏包的大小。

  • 这是一个非常好的功能,如果 unity 不提供自己写插件恐怕还是比较麻烦的,但是在使用过程中有没有“坑”呢?有没有要注意的地方呢?答案当然是:有!

  • 如果你在场景中有动态切换材质(主要是 shader 的改变),比如原始模型中带有法线,默认的材质没有使用法线,但是动态切换的材质却需要使用法线,那么你得注意很可能在编辑器中运行正常,一旦发布到真机就会出现很怪异的现象,会让人以为是 shader 在不同平台的兼容性或者数据精度等问题。譬如描边效果就是一个很好的例子。

  • 结论:如果使用此选项,请务必注意自己动态切换材质的游戏对象是否在场景中以静态的形式存在,shader 使用了哪些模型的数据,并根据实际情况做相应的调整。

有没有什么办法可以提升Unity编辑器中代码的编译速度?我们现在每修改一次代码,等待的编译时间都将近半分钟。

  • 对于大型项目来说,这确实是大家经常遇到的情况。一般来说,Unity Editor会按照脚本的依赖关系编译代码,其主要分为以下四个步骤:
    • 编译Standard Assets、Pro Standard Assets和Plugins文件夹中的Runtime Script;
    • 编译以上三个文件夹中Editor文件夹下的Script;
    • 编译项目中所有剩余的Runtime Script(Editor文件夹以外Script;
    • 编译剩余Script(即Editor文件夹中Script)。
  • 建议研发团队可以将一些长时间不需要改动的脚本代码(比如各种插件代码)放入到Standard Assets、Pro Standard Assets或Plugins文件夹中,这样这些代码只需要编译一次,后续的时间就都能节省下来。

纹理

如果纹理尺寸长宽不相等,那么即便是2的幂次,也不会被压缩成PVRTC格式纹理。建议在iOS平台中,尽可能保证纹理尺寸为2的幂次且长宽相等。

UI

NGUI中不同panel下的Widgets使用同一个Atlas,会导致DC比较多,而且从profile中会有多个同名的mesh,以为NGUI中这些widgets的mesh是动态生成的,名字采用的就是Atlas的名字。

对于NGUI而言,如果界面元素的坐标是非整数的数值,会导致界面元素模糊么?还有哪些原因会造成界面元素模糊?

  • 导致界面元素模糊的原因主要分为两个,
    • 一是像素未对齐(通常就是因为坐标非整数造成),在相邻像素色差较大的情况下容易出现模糊,特别是文字部分;
    • 二是纹理分辨率相对于屏幕的分辨率被缩小或放大,纹理被缩小通常会表现出锯齿感,而纹理被放大则会表现出模糊。
  • 而对于动态字体,通常只需要确保像素对齐即可使其不模糊,但需要注意的是,UGUI与NGUI都有全局缩放的功能(分别在Canvas Scaler和UIRoot组件上),是为了确保不同分辨率下布局相同,也会使动态字体出现缩放,从而造成模糊的问题。

工具

Draw Call和Setpass Call,这两个指标主要是看哪一个?关于这点众说纷纭,很多地方都是说看SetPass Call,但是在UWA的性能测试中,还是把Draw Call当成唯一指标。

  • 在 Unity 5.x 中,SetPass Call与 Draw Call相比,SetPass Call的指标与性能相关性更大(比如Static Batching的开启不影响Draw Call数,而SetPass Call通常会明显下降)。
  • 但 SetPass Call在某些情况下也同样存在问题,比如往一个场景中添加任意个相邻且材质相同的大网格物体(使Dynamic Batching失效)时,SetPass Call并不会变化。因此在UWA中,我们所使用的是类似Profiler 中 Total Batches 这一项指标,通常该数值与 Frame Debugger 中的数值基本一致,因此可以通过该工具来查看每个Batch的内容,从而更有针对性地进行优化。

Shader.Parse 和 Shader.CreateGpuProgram 到底是做什么的?它们什么时候执行?

  • Shader.Parse体现的是Shader的加载和解析, Shader.CreateGpuProgram 是将Shader传入GPU的一次提交,GPU驱动会对其进行编译,以适应于特定的设备或平台。
  • 在Unity 5.x版本中,Shader.Parse在Shader资源加载时进行执行,而 Shader.CreateGpuProgram在所在GameObject第一渲染时进行执行。

模型&动画

关于Mesh合并的问题

勾选了static的对象

  • 只要是勾选的static的对象都会合并mesh,而不考虑材质使用问题。每个对象会变成submesh。
  • Unity 5.3之前,对于渲染顺序相邻且材质相同的SubMesh则会动态将其索引数组拼合,从而合成一个Draw Call。而Unity 5.3之后则不再拼合索引数组,因为在不切换材质时产生多个Draw Call的开销并不大,而这多个Draw Call会被统计为一个Batch。

    对于动态合并的对象

  • Unity对于任何Mesh的面片都有65536的个数限制,拼合后的面片数也是如此。

请教,角色分部件换装可行吗?比如衣服裤子分开,都是用Skinned Mesh Render,有没有办法合并降低Draw Call?

  • 可以通过合并网格的方式来达到降低Draw Call的效果,具体可查看Asset Store中的换装例子:Character Customization。但是,在角色换装时需要注意以下几点:
    • 装备与角色必须是共用一套骨骼的;
    • 各装备之间所用的材质必须相同。
  • 开发者需要注意,只有同时满足以上两个条件时,才能达到只使用少量Draw Call来进行动态换装的效果。

渲染

要达到后续Shader都不出现加载开销,需要满足以下两个条件:

  • 包含Shader的AssetBundle文件常驻内存;
  • Shader已经全Load加载好;