每帧时序与步进
需要:uBotPhysics 0.1.x(含依赖 uBotCore)
了解后端的步进和位姿回写在每帧的什么时候发生,以及一帧需要的步数太多时会怎样。
后端的步进和位姿回写发生在每帧的 TG_PrePhysics,游戏暂停时不运行:
| 阶段 | 发生了什么 |
|---|---|
TG_PrePhysics |
需要时扫描场景;每个求解器先收到场景的变化,再按自己的步长补到不超过当前仿真时间;所有求解器都步进完之后,把被绑定物体的位姿写回对应的组件 |
TG_DuringPhysics |
Chaos 模拟其余的物体,被绑定的组件作为运动学体推动它们 |
TG_PostPhysics |
传感器采样、ROS 发布 |
每个求解器有自己的固定步长,范围 0.0001 s 到 100 s。
- 求解器的时钟在第一次有物体、且子系统第一次运行时启动,第一步在启动时间加一个步长处结束,之后的步都落在这条网格上。
- 所以求解器的时间从不超过仿真时间;暂停期间不步进,恢复后也不补跑,见仿真时钟与采样调度。
- 一个求解器的物体都解绑后不再步进,下一次有物体绑定时时钟重新启动。
- 一帧可以走好几步,也可以一步都不走(帧比步长短)。这一帧没有步进时,位姿照样写回,场景更新也照常发送。
一帧需要的步数超过每帧上限(默认 1000)时,最早的步照常执行,其余的被跳过且不补跑。跳过的步数用 Get Dropped Physics Steps 查询,大于 0 就说明物体的运动比仿真时间慢了。
连线:
- Event Tick 的 执行,连到 Print String 的 执行
- Get Dropped Physics Steps 的 Return Value,连到 To String (Integer64) 的 In Int
- To String (Integer64) 的 Return Value,连到 Print String 的 In String
Backend填后端名,这里的MyBackend只是示例。
Event Tick
UE 引擎 · 中文界面:事件Tick
Event called every frame, if ticking is enabled
输出
- 执行
- Delta Seconds
Float
查看参考AActor.ReceiveTick
Get Dropped Physics Steps
uBot Physics Library · UBotPhysics
这个世界里 Backend 因为一帧需要的步数超过每帧上限而跳过的步数。跳过的步不会补跑,计数一直累加。
输入
- Backend
Name
输出
- Return Value
Integer64
查看参考UUBotPhysicsLibrary.GetDroppedPhysicsSteps
To String (Integer64)
UE 引擎 · 中文界面:转换为字符串(Integer64)
Converts an 64-bit integer value to a string
输入
- In Int
Integer64
输出
- Return Value
String
查看参考UKismetStringLibrary.Conv_Int64ToString
Print String
UE 引擎 · 中文界面:打印字符串
Prints a string to the log, and optionally, to the screen If Print To Log is true, it will be visible in the Output Log window. Otherwise it will be logged only as 'Verbose', so it generally won't show up.
输入
- 执行
- In String
String - Print to Screen
Boolean - Print to Log
Boolean - Text Color
Linear Color结构体 - Duration
Float - Key
Name
输出
- 执行
查看参考UKismetSystemLibrary.PrintString
- 丢步的原因是帧太长,或后端的步长太短。
- 丢步的计数在世界里累计,不清零。
- 每帧上限在 C++ 里用
UUBotPhysicsSubsystem的GetMaxStepsPerFrame和SetMaxStepsPerFrame读写,默认 1000,至少为 1。
- 位姿回写以步为单位,不做外推:没有丢步时,组件的位姿落后仿真时间最多一个步长。
- 丢步之后这一点不再成立:被跳过的步不会补跑,物体的运动比仿真时间慢,差距是丢弃的步数乘以步长,直到这个求解器的时钟重新启动。
- 回写时附着父级在前、子级在后,跨后端也一样,所以父子两个组件都被绑定时,子组件落在自己求解器给出的位姿上。
- 后端给出的状态不是有限值时,这个物体的位姿不会写回,组件停在上一个位姿。