Unity引擎制作万人同屏效果
大家好,我是阿赵。
之前介绍了我的万人同屏渲染的做法。其核心就是用VAT代替骨骼动画,用Shader来播放顶点动画。
但做到这一步还不够,因为如果模型都是单独渲染,就算全部推到GPU去计算,由于渲染批次没有得到合并,所以当模型多起来之后,GPU的压力还是会很大。
这时候,首先想到的手段可能是GPU Instancing。没错,这个技术可以合批渲染。但使用GPU Instancing的条件,是需要同一个网格模型同一个材质球的。可以想象一下,场景里面有上万个角色在动,它们都使用了不同的网格,不同的动作使用的是不同的材质参数,GPU Instancing能合并多少个角色渲染呢?
所以我选择了SRPBatcher。SRPBatcher的使用条件比较简单,只要是同一个shader变体就可以合并,可以是不同的网格模型,可以是不同的材质球。
SRPBatcher具体是怎样使用的,我这里就不再重复了,因为之前已经写过文章专门的介绍过了,有兴趣的朋友可以往前翻一下。
这里只来看看实际的效果,我这里使用的是URP渲染,在没有开SRPBatcher的时候,可以看到渲染的次数非常的恐怖,总共渲染了一万六千多次。
![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/08ab841faa1349709e36157784233357.png#pic_center)
当把SRPBatcher打开之后,就会合并成只有几次渲染了:
可以发现,同样渲染一样的数量的动画模型,这个时候帧率就高了很多了。
SRPBatcher是比较容易见效果,但在使用的时候,也有一些东西需要注意的,不然可能会出问题。
1、SRPBatcher对于渲染管线的支持
首先SRPBatcher是不支持默认的内置渲染管线的,如果想使用,请使用SRP,比如URP或者HDRP之类的渲染管线。所以我这个例子使用了URP。
2、SRPBatcher对于材质参数的要求
SRPBatcher快的原因,是把材质数据保留在了GPU里面,如果材质内容不变,就不需要设置缓冲区域和上传到GPU。所以对于使用MaterialPropertyBlock来改变材质参数,就会破坏SRPBatcher,让合批失败的。
然后尽量不要频繁的设置材质参数。我之前的VAT实现Shader里面,为了照顾播放一次的非循环动作,也有设置当前帧的做法。不过这样做是会频繁改变材质参数的,所以能循环的情况下,尽量用Shader本身的循环播放功能,用StartFrame来产生循环的随机性就行了。如果循环动画也用C#之类的脚本不同的从外部设置材质球的当前帧,那么就等于SRP没有任何效果了。
我曾经想过连位移旋转缩放也放在Shader里面做,但如果那样做,当物体运动的时候,也是会频繁改变材质参数,所以那样反而没有起到优化的效果。
3、SRPBatcher对于移动平台的支持
最后,SRPBatcher在PC上面很容易就生效了,但在移动平台上面,却一直不生效。这个问题困扰了我好几天,我一直怀疑自己是不是哪里写错了。后来在网上查找了很久,才相信,这个居然是Unity引擎的Bug,在某些版本的Unity引擎里面,SRPBatcher在移动平台会不生效,一直合并不了。
具体可以看看这个帖子:
官方论坛帖子
为了节省大家时间,看看这段官方技术的回复,这个问题在某些Unity版本里面修复了:
于是我换了一个Unity版本,问题就迎刃而解了。所以有时候不要太钻牛角尖,有可能问题不是出在自己的身上。