【Unity】粒子特效优化实践

  对于移动平台来讲,一直不建议大量使用粒子特效。因为对CPU和GPU来讲,粒子系统都是一个性能消耗的大户。但是现在粒子特效在游戏中的需求越来越高,因此做了一些Unity粒子优化方面的尝试。由于针对移动平台,因此不考虑Computer Shader这种DirextX11的特性。

  拿来做优化实例的粒子特效,包含5个粒子发射器。类型为Billboard的粒子X3,Mesh粒子X2。其中一个Billboard粒子和一个mesh粒子共用了一个材质。对于这个粒子特效来说,5个DrawCall,一个都没有Batching掉。

  然后我们将这个粒子复制10个,发现成功Batching的只有billboard粒子,Mesh粒子没有动态Batching。

  按照其官方文档来讲,Unity动态合批的规则比较苛刻。首先材质必须一致,其次顶点属性个数不超过900个【实际上已经支持远不止900个了】,对于一个Shader,如果包含了顶点位置,UV,顶点颜色三个属性的话,那么这个个数就只有300个。

  对于Billboard粒子来说,它基本上会符合上述的要求,因为Billboard粒子抛弃了这些属性。但是对于Mesh粒子来说,需要共用同样的材质。

  表面上的规则是这样的,但实际应用上有所差别。

  首先是Billboard粒子,即使是使用相同材质的粒子,也要保证这些粒子在渲染队列中是连续的,否则不会完全的Batching。这就需要在粒子的Renderer标签中设置Sorting Fudge/Sorting Order/Order in Layer来保证它们的渲染顺序连续。但是调整Render Queue的弊端也比较明显,特效er在制作特效的时候,并不一定希望相同粒子的渲染队列连续。因为对于半透明物体,渲染顺序会影响他们的显示效果。

  其次是mesh粒子,这个的问题在于多次尝试,依旧没有一次成功Batching掉的经历。即使使用的Mesh是一个Quad,发射器发射的粒子很少,绝对不会超过300个顶点限制的粒子。复制多个出来,依旧不会batching。但是并没有在Unity的官方文档中找到Mesh粒子不会被动态Batching掉的相关说明。所以这块到底真实情况如何我也不能保证,如果有尝试成功的一定要告诉我。

___________________________________________________________分割线____________________________________________________________________________

  然后就是一些其余的尝试。

  首先是合图,这也是Unity的文档中动态合批时给出的建议,在多个不同的粒子中使用一个材质球。但是根据我的尝试,在Mesh粒子中并不适用。Mesh粒子虽然有UV,可以进行合图。但是如上述所说,并不会动态合批,最终的结果只是减少了一个材质球而已。Billboard粒子通过Texture Sheet Animation中的设置可以实现有限制的UV分割(感谢@柒夏爸爸 指正),不过用于UV分割是均分,合并后的纹理不能公用空白区域,会有些浪费空间。

  尝试使用Shader+脚本的方式来代替粒子效果。

  对于一些简单的粒子效果,理论上完全可以使用Shader+脚本的方式来简单模拟。因此,我尝试性的写了个Shader,通过顶点着色器来实现旋转,放缩,Billboard效果。

  用Shader+Quad的方式代替之前特效中的几个粒子发射器,然后复制多份,打包到安卓平台监视性能。令人惊讶的是,和使用Billboard动态合批优化后的粒子比,CPU性能消耗高了不少。原来的粒子特效复制十个摆放在场景中,CPU的渲染在10ms+,DrawCall在100以内。修改之后的效率是CPU渲染12ms左右,DrawCall 110左右。简单的分析原因就是上面讲过的,首先是这些替代的Quad完全打乱了的billboard粒子的渲染队列导致不连续不能动态Batching,导致DrawCall增加,CPU时间占用提高。不过从OverDraw来看,GPU倒是释放了部分的性能,但这往往以效果的牺牲为代价。

  但是Mesh的渲染队列调整只能在Shader中修改Queue或者脚本中调整SortOrder【Unity2017已经支持直接在材质设置渲染队列】,如果使用同个Shader来应用不同的Material,需要加脚本来控制SortOrder排序。

  根据新的尝试,使用Shader通过顶点着色器实现旋转,缩放,Bllboard,在片段中实现闪烁和序列帧播放效果,从功能上来说,并没有问题。但是真正的问题是出在动态Batching上,使用顶点动画的Mesh,在动态Batching下会出现顶点位置的异常。目前没有找到很好的解决方案,如果在Shader中DisableBatching的话,性能的消耗代价太大。

posted @ 2017-09-11 10:42  JaffHan  阅读(16873)  评论(5编辑  收藏  举报