我们游戏中有一个建筑破碎的需求。在一个很宽敞的地方,播放一段sequence。Sequence中,Boss会攻击主角,导致附近的几间瓦房碎裂。因为有瓦片,有相当多的碎片。可以预期的是实时计算开销很高。加上游戏运行的基础开销,预期中就不是一个能够流畅运行的设计。
因此从一开始,我们就准备尝试Chaos cache来解决这段sequence中,含有破碎表现的这些效果。
我们给boss创建了物理资产,全身都有大致恰当的胶囊体和球体,也做好了破碎资产。期望在sequence播放的过程中,通过动画和物理资产,自然的撞击破碎资产,引起破碎,并将结果录制下来。
首次测试的时候,发现房屋被打飞。于是我们增加了锚定场。碰到了3个问题:
1、原本破碎资产的“general”-"Object Type"属性设置成Dynamic是可以被打动的。但是锚定之后,对于sequence中boss的攻击完全没有碰撞。
2、为了解决问题1。我修改为sleeping。修改之后,可以打碎,但是碎裂的效果明显不对,有许多穿模的现象,还有很多该碎的碎块没有脱落的问题。
3、在上述的情况下,破碎资产因为受到撞击,整体还会有短距离的位移。
考虑到可能是在首次命中的时候力量过大导致的,想到可以先让资产碎裂,之后发生的撞击,不但自然,也不会导致资产整体发生位移。于是增加了破碎场,在恰当的时机启用,在撞击前,让破碎资产先断裂。
在此之后,录制非常顺利的结束了。但是在使用缓存的时候,又碰到了新的问题:
4、缓存的效果和sequence中的动作,怎么都对不上。
无论我们怎么调整“start time”,都无法匹配的上整段sequence中的动画。在排查匹配不上的这个过程中,我们花了不少时间去分析场景的影响、sequence是不是有时间膨胀……最终我们留意到破碎缓存的Recorded Duration时间有问题。我们的sequence是60的帧率,总共2140帧,大约35秒。但是我们录制的破碎缓存,只有21秒。并且在sequence播放之前,还等了10秒。于是我们开始使用录像软件录制桌面,录制的时候,将缓存中的"Recorded Duration"参数录制下来。最后分析录像的时候,看到游戏中等了10秒之后,cache中的“Recorded Duration”只有6.几秒。sequence播放完了,cache中的“Recorded Duration”才只有21不到。
我们还没有来得及看代码。但是主观猜测,可能是游戏因为卡顿,导致两帧之间的间隔较大(超过16ms或者33ms)。而物理的最小帧间隔是0.033秒。为了保证模拟效果的连续,即使游戏两帧之间的间隔高于33ms,也只能采用33ms作为时间步长来进行计算,否则在表现上就会出现显著的跳变,带来许多其他问题。如果是这样,那么只要录制的时候,帧率不够,必然会导致缓存记录的数据,和sequence的时间轴不匹配。
以上是我们碰到的问题。
附件中是为了还原我们碰到的情况,准备的一个测试工程,还原了我们的用法及碰到的情况。如果处理问题的伙伴电脑配置相当好,RecordLevel运行起来一点都不卡,可以将关卡中的破碎资产,替换成GC_Cube3。CacheLevel关卡是使用缓存数据进行的关卡。