UE 5.8.2: custom C++ autopilot diverges from fixed-step forecasts with variable frame deltas

Hello everyone,

I am developing MEGACUBE 2.0 in Unreal Engine 5.8.2 (CL56702186), on Win64. I would appreciate guidance on input scheduling and safe replanning for a custom C++ gameplay-test autopilot.

Our AActor runner uses a project-defined simulation, not CharacterMovement. The simulation subdivides an outer frame into steps of at most 1/90 second and holds the selected input throughout that frame. Gameplay allows a jump for 100 ms after support is lost. The test controller selects movement and Space once per outer frame before the actor update, and evaluates maneuvers on an independent copy of the same simulation.

At a constant 60 Hz the native route check completes its first two route legs. With recorded variable frame durations it originally failed at target 341: a 144.907 ms frame let the controller walk off support and exhaust the grace window before Space arrived. The forecast had used the known initial delta and assumed 1/60 second for later frames. We added a bounded pre-step revalidation of that committed walk-off maneuver, preserving native physics and the test criteria.

The single control after this correction passed that point but still failed later at target 535. During a 118.394 ms outer frame the runner landed on route leg 1 while its requested target remained on leg 0; the planner then reported no verified continuation to that previous-leg target. The hero was still running, not dead. Five related native checks succeeded, but complete route acceptance remains failed. We have not established the exact earlier command-selection cause of this remaining contact.

We are investigating our test controller, not reporting a demonstrated Unreal Engine bug. Simply jumping earlier everywhere is not validated: another route case requires a short, late jump to avoid landing on the next route leg. We need to preserve gameplay physics, route geometry and ordinary per-frame input delivery.

Is there an official UE 5.8 example or recommended pattern for safely revalidating predictive input commands throughout a maneuver when a custom simulation uses internal fixed substeps but actual outer frames vary? In particular, can you recommend an engine-supported scheduling or test approach that does not rely on knowing future frame durations or altering gameplay jump rules?

We have checked Actor Ticking, AActor::Tick, FWorldDelegates::OnWorldPreActorTick and Physics Sub-Stepping documentation. We understand that Chaos substepping settings do not control our custom simulation.

Thank you!

Following up on this question: any guidance or official UE 5.8 examples would be appreciated. Thank you.

There is no UE 5.8 sample for this. Chaos substepping and OnWorldPreActorTick will not schedule a custom sim, which you already found. The pattern that holds up is to make the outer frame a delivery boundary only, and to re-score a committed maneuver whenever the dt it was scored with is not the dt you are about to integrate.

Your 144.9 ms failure is the input latch, not the 1/90 integrator. Space is chosen once, before the actor update, and then held for every substep of that outer frame. A 145 ms frame is about 13 substeps of 1/90. Those substeps still carry the previous frame’s input, so the 100 ms grace window expires inside the frame, before the jump you just selected is applied. At a steady 16.7 ms this never shows, because the grace window spans several outer frames. Clamping the forecast to 1/60 after the first recorded delta hides the same bug: the predictor and the playback are not consuming the same clocks.

Do this without changing the jump rule and without knowing future frame times:

Score the maneuver against the dt you actually have, which is the delta passed into Tick for this outer frame, not a guessed 1/60 and not a raw recorded hitch if the world will clamp it. Project Settings > Engine > General > Max Delta Time, and any clamp you apply before the sim, have to be inside the copy the planner runs. If the game will only ever integrate 50 ms of a 145 ms hitch, the forecast must see 50 ms.

Apply the chosen input at the start of each substep, or at least re-check it at each substep boundary that crosses the grace deadline. Holding one input across a whole outer frame is what lets a hitch burn the 100 ms window. Re-reading the already-chosen command per substep does not press the jump earlier in gameplay. It stops a late command from being deferred until the next outer frame.

Keep the bounded revalidation you added, but trigger it on dt mismatch, not only on the walk-off case. Before each outer frame, if the dt you are about to simulate differs from the dt the committed maneuver was verified with, re-run that maneuver on the independent copy with the new dt and the same jump rule. If it no longer reaches the target, discard it and pick again. That is the whole “safe replan” step, and it does not need future durations.

The target 535 failure is the same class of bug one leg later. A 118 ms frame let the runner land on leg 1 while the committed target was still on leg 0, so the planner looked for a continuation to a target the body had already left. Revalidate the target against the post-step state, not the state from when the command was chosen. If the body is on leg 1, the previous-leg target is stale and “no verified continuation” is the correct rejection. The fix is to refresh the target from the post-integration leg before asking for the next command, again using only the dt you have now.

For the test harness, drive both the native run and the copy from one clock. Either tick the world at a fixed delta (fixed frame rate, same dt every Tick) when you want a deterministic check, or feed both the recorded dt after the same clamp. Mixing a variable recording with a forecast that assumes 60 Hz will keep failing at whichever hitch is longer than the grace window.