I was doing some research on how Unreal engine handles the physics update, and I could not find a lot in the official manual. Most of it comes from the Physics Substepping manual page and a few remarks from a fellow Unreal dev. I have seen a few similar threads on the topic but they are already a few years old and there wasn’t a satisfactory solution for me.
I wanted to have a physics update loop behaviour like in Unity, where the update deltaTime is always consistent. This way, physics can behave consistently even on lower or variable visual framerate. Here are my requirements:
- Every physics step should simulate with the same deltaTime value
- The physics time tries to catch up with the regular simulation time, but will simulate no more than a maximum allowed physics timestep for each visual frame. If the physics time can’t catch up, physics simulation simply slows down, but will never use a variable deltaTime as simulation input
- It doesn’t matter whether or not the simulation steps happen evenly spread out in realtime or in bulk. Example: The Unity event loop has a step where synchronization with the physics happens. A visual frame might run 0 physics updates, or it might run 3+ physics updates, depending on the visual frame deltaTime. physics updates happen consecutively in realtime. In this case, 3 physics frames would be simulated in a row, then no physics frame happens for a while, and in the next iteration of the unity event loop, this process is repeated
- Results from the physics need to get synced with the engine state that is accessible in the Tick and other methods. Physic event callbacks need to be received by actors for every step, not only at the end of a sub-stepping chain. If not possible, at least there needs to be a way to run custom code between each physics step in the physics thread, even if only the state of the physics world is accessible and up to date - and event reactions need to happen in custom code on the physics thread then.
Here is my interpretation on how Physics act in Unreal. Please correct me if I’m wrong since I don’t have a lot of insight on the internals of the engines:
- Unreal uses variable frame rate for physics deltatime, to stay in sync with visual updates
- You can activate physics substepping to make it more consistent, which means to split an update frame up into several frames if possible, under the consideration of a max timestep. The step deltaTime might not be 100% consistent since it accumulates the remainder to reach the visual frame time (not quite sure about this last point)
- You don’t receive collision callbacks until after all substeps for one frame are done. Some object state changes on Unreal actors are only applied after all substeps have finished
- You can’t intercept with custom physics logic between the substeps, to apply forces for example (if there was a way to allow for this on the physics thread, it is appreciated. Or maybe there is a way?)
Unity also allows for the following, which could be used to manually implement the requirements above. Maybe Unreal has a similar API somewhere?
- Disable the automatic physics simulation
- Code your own update loop logic.
- The physics step can be called with a deltaTime parameter. It will step the physics world forward by this value. The calls have to happen on the main thread thread because Unity doesn’t allow such API calls on other threads.
I’m aware that the suggested approaches are less efficient since there are more times where synchronization with the main thread needs to happen to apply the results of the physics calculations multiple times per visual frame.
If this isn’t possible with any built-in API, would it be necessary to customize the engine source code to achieve the desired result? If the regular engine builds allow for this, which API methods can I look into to customize the physics loop?
Thanks for reading my question to the end, any input is appreciated!
Update: I just read about the “enhanced determinism” physics option, but it seems like the last slice of the physics-substepping will still use a detaTime that is smaller than/different to the other substep deltas. Here is a very promising thread:
Is the “enhanced determinism” option the closest thing there is for achieving what I want? Do all other solutions basically require you to adjust the engine source code or use a different physics system?