UE 粒子优化记录

1. LOD与设备分级 

   高配机使用LOD0 低配机使用LOD1  使用r.ParticleLODBias = 0/1 来切换。

2. 粒子合批

  同一个粒子发射器发出的粒子都是一个批次的,在使用过程中让瞬发型的粒子从同一个粒子发射器中发出,如枪火特效,命中特效等可以大大减少draw call的数量,用EPSCPoolMethod.ManualRelease手动释放的池模式来hook住这个粒子,在使用时设置到对应的位置再SetActive(true, true)来达到重复使用的效果。

特别的ue自带的粒子事件AnimNotify_PlayParticleEffect, 他的实现是无脑重复生成粒子,可以进行适当的改造改成上面的做法。

3. 粒子池

  粒子池是ue已经实现的较成熟的模块,只要设置正确,让美术/客户端同学会使用即可,(详细分析见本人另一篇)

3. 尽量用Mesh来替代粒子

  能不使用粒子就不使用的原则。例如子弹拖尾,如果使用ribbon粒子来实现会有额外的trail计算开销,

这种可以使用一个面片+材质来实现,材质接收抛体的路径信息(可以提前计算出轨迹 速度等信息给材质)来画出目标抛物线,按时显示就是拖尾效果。

同样的,投掷物的瞄准线(一般用beam粒子/spline mesh来实现) 也可以使用面片+材质的方式来进行优化。

4. 性能和表现的权衡,各种方式的融合使用。

    喷火枪使用mesh(打开overlap响应)+粒子来实现。

    地面火焰使用deferred decal+粒子来实现。

    这类表现具体内容具体分析实现方法。

5. 粒子光照

  场景中允许使用的光不超过4个,假如给表现燃烧效果的粒子加上粒子光照,往10个敌人中扔个燃烧弹就会出现11个光源,mobile的gpu会吃不消,所以在制作中动态生成的特效尽量不加light模块,或者将light模块加到最低重要性配置中(Significance Manager)。(参考原神的特效没有任何光照)。

6. 粒子bound

     决定如何剔除粒子,确定粒子的可见性(GPU消耗)

     在项目中使用fixed bounds, 这个代表相机在bound内无论如何都会渲染粒子,在bound外走正常的遮挡剔除逻辑。

     (默认计算的bound极大而且会随粒子tick计算大小,会出现人在地面上还在跑地下车库的粒子的情况,浪费性能较严重。)

    

1-6部分都是粒子与场景中的其他功能交互时的优化点,也是我进项目以来挨个踩坑/实现的经历。

以下是粒子本身的优化。

7. 粒子自身优化:

数量:整个particle的emitter的数量不大于5,单一emitter的粒子发射数量不要超过16,尽量减少单个emitter内部的module数量以减少memory开销;

Static Mesh:有的emitter需要使用到static mesh,不要存在一个static mesh对应多个material ID的情况,一个static mesh的material只能有1个;Static mesh的面数要尽可能缩减,特别对于一些体积非常微小的mesh(比如爆炸出的微小石子完全可以控制在20面以下);

Overdraw:要尽量避免减少粒子之间的重叠覆盖,这个非常重要;
a. 可以通过线框模式检查粒子面片之间的叠加情况,通过减少发射数量降低叠加程度;

 ->

b. 在emitter的”Require”一栏下,改变Particle Cutout来减少粒子间覆盖程度:
具体overdraw的严重程度判定及标准见“Shader Complexity”;

c. 视觉效果允许下改变particle形态使粒子之间分散一些;
d. 视觉效果允许下,粒子不要太大,比如释放出来会占满半个屏幕的那种大的特效,尽量少一些或者没有,如果实在需要,在制作和优化上要格外小心谨慎;

 

 

8. 粒子单例管理器的使用 FParticleSystemWorldManager    自带batch粒子的tick 默认8 这里可以获取场景中所有的粒子(但强制要求粒子无子component 这个判断可改下) 。新加管理重要度更新,管理粒子当前是否渲染来停止tick(或者降帧), psc开参数来控制这个优化行为,因为有些粒子与逻辑强相关(在设计模式上不科学 但是为了表现没办法)

粒子tick 默认开启task_graph的多线程模式 (task graph, async task, runnable,3种异步之一,适用于较简单的任务,  需要实现 get id,get 需要的线程,do task,创建的时候需要前置任务,目标线程,自己的任务 )粒子本身tick_component lod  粒子异步compute_tick_component   所有instance的每个module的变化,计算粒子bound的变化

 

 

 

  

 

posted @ 2021-11-15 14:28  Adam_TT  阅读(531)  评论(0编辑  收藏  举报