虚幻引擎:时间脉动(Tick of Time)

5

主题

9

帖子

19

积分

新手上路

Rank: 1

积分
19
发表于 2023-1-17 14:45:10 | 显示全部楼层
将虚幻引擎用于科研仿真时,需要保证:

  • 实验可重复
  • 运算结果和宿主机器的硬件速度无关
  • 与渲染无关
  • 可以把仿真过程加速,迅速计算取得最终结果
  • 可以把仿真减速用于观赏,录制视频等等
然而虚幻引擎本身的时间系统是比较复杂的,在实现上述需求过程中踩了不少坑,
其中一个甚至是虚幻引擎浮点数精度导致的“蝴蝶效应”。
整理经验如下:
1、锁住虚幻引擎的帧率(FrameRate)

这个可以在Project Setting, Engine, General选项里面设置为固定值,也可以用C++调用GEngine函数处理。


这里的帧率最好设置为32,64等(2的整数次幂),作用后面会提。

2、时间膨胀系数(Global Time Dilation)

虚幻里面一个很方便的功能就是这个时间膨胀了,直接就能实现全速计算的功能。也就是说一个1分钟的仿真过程,我们可以利用时间膨胀Time Dilation的设置进行加速,当Time Dilation足够大时,完成这个仿真的计算时间完全取决于CPU的性能。


有一点需要注意,TimeDilation有默认的上下限,(默认时0.001到20),如需修改,请去World Setting改,如图:


3、实验结果可重复性:时间膨胀系数和帧率的配合

在仿真时,肯定希望无论如何加速计算,我们总能获得一致的结果,这就要求每个Tick的时间间隔(Delta Time,下面简称dt)是固定的。
在虚幻引擎中:
dt = 时间膨胀系数 / 帧率 =  TimeDilation / FrameRate
显然,为了保证结果一致,我们必须同时修改二者,例如(TimeDilation=1.25, FrameRate=64),
(TimeDilation=2.5, FrameRate=128)等等。

4、蝴蝶扇动一下翅膀,Bug调一天

仿真里面是有“蝴蝶效应”的,即使按照上面的公式进行了dt的控制,可是当TimeDilation改变时,
运算的结果依然大相径庭,这是为什么呢?

原来虚幻的deltaTime时间在传参的时候采用的是32位浮点数,当帧率是60时,本来dt应该为
dt = 0.0166666666666666666666666666666
(没有考虑TimeDilation,因为TimeDilation是后面才乘上去的)
但在32位浮点数下,dt只能表示为
dt = 0.016666668
这小小的误差就是蝴蝶翅膀,随着运算的进行,逐步被放大,最后导致灾难性后果。
解决这个问题也很简单,众所周知,计算机都是二进制数,
如果帧率设置为2的整数次幂的话,帧率的倒数dt自然也是2的(负)整数次幂,如此一来,
32位浮点也可以完全精准地表示时间啦!蝴蝶效应的影响就自然消除了。

5、这瓜你要不要吧:虚幻的物理引擎

虚幻4里面的物理引擎支持sub-steping,我的理解是在游戏的frame之间再插入若干次计算。不过这个默认是关闭的,所以暂时不予以考虑。
然而这里还有一个神坑:


这个设置里面的Max Physics Delta Time对输入进来的dT会进行二次修改。
具体而言,就是如果dt超过了这个值,物理引擎会拒绝承认这个dt,用max physics delta time取而代之。
这个功能设计的初衷是防止dt太大导致离谱的物理运算结果产生(碰一下就螺旋升天等bug),
这里我们想让引擎的所有运算都臣服于统一的dt约束,所以需要把max physics delta time加大,禁止任何不受控的因素出现,一般0.5就差不多了。
您需要登录后才可以回帖 登录 | 立即注册
快速回复 返回顶部 返回列表