Async Physics and Physics Control

We have a large complex project where we’re having issues with Async Physics and Physics Control (via Physics Control Component and Physics Control Asset). To repro and get to the bottom of it I assembled a minimal sample project in 5.7.4 which also works in 5.8 and reproduces there too.

The issue we have in our main project that led me down this path is we have creatures where parts of the creature are kinematic and parts are simulated. For example a kinematic head and root and simulated body parts, tails, etc. We are an underwater game so there’s a large amount of linear and angular drag on all bodies (3.92 linear, 0.735 angular). They always have completely locked constraints on all linear constraints and relatively lose angular constraints. The problem is that the simulated parts often don’t move at the same time as the kinematic parts and stretch away from them and then spring back. This often causes overshooting and extreme stretching. It is worse when there is low FPS (<30) and very noticeable when there are hitches.

I put together a sample project with 3 different ways of moving a sample rig, all have the same physics and physics controls. One moves the actor location every frame, one moves the actor location every few frames and smooths the skeletal mesh in the inbetween frames and one uses the stock CMC. All assets have world controls (just defaulting to 0,0,0) on simulated parts and some kinematic parts near the front. I put them in a test map and then tested with and without async physics.

I noticed the following:

  • Without async physics everything works great with all movement styles
  • With async physics teleport thresholds on the physics control were hit which were not when async physics was disabled (can test by setting teleport threshold to 300 in the physics control component in the sample project) causing bunching and jumps in the physics
  • With async physics enabled and teleport disabled (to reduce variables at play) the physics constraints are entirely broken, locked linear constraints are not respected at all and bones are stretching 3x their length, drag appears to be multiple times stronger and the bone at the front (I believe root?) is far offset out of the front of the skeleton.
  • CMC has slightly better physics than the other movement methods but still noticeably broken compared to async physics off, better velocity being passed to the sim maybe?

I have attached two images before one with async physics off and one with async physics on, everything else the same

Async Physics Off:

[Image Removed]

Async physics on:

[Image Removed]

Now I expect some amount of delay/physics being behind the gamethread/render with the physics being async or perhaps some cvar wrangling to get things working nicely, but in our actual project I have tried dozens of different options and none of them seem to help. The physics with async physics enabled are more unstable across the board (expected somewhat but this is more than expected) and constraints are not being respected at all and it’s causing noticeable stretching and bunching in our game with creatures that mix kinematic and simulated parts. I’ve tried various different options within the physics asset, physics control, chaos cvars including some intended to sync anim, game thread and physics frames in various ways.

Is there something we’re missing? We have to have async physics enabled for a completely different unrelated reason (was recommended by Epic to support another part of our project) so we desperate to figure out how to resolve this and I’m all out of ideas.

[Attachment Removed]

Steps to Reproduce
Open sample project, open “NewMap”, run PIE, pause the game, detach and step through frame by frame, repeat with Async Physics enabled and disabled in the settings and notice the difference.

[Attachment Removed]

Hi Sam, and thank you for the explanation and the repro, that has helped a lot in figuring this out.

The good news is that this is very likely a setup issue more than anything specifically to do with async.

  • The first callout is that there is a difference between what the frames are doing, and the physics. In the blueprint you have a per frame movement - ie nothing is factoring in how long that frame took - so all of these are moving the same amount per frame regardless of whether it is running 100fps or 10fps. The means the physics engine (which is being run at a very specific time delta) is getting in a very different amount of movement every frame which causes huge issues for the constraints. To fix this, all you need to do is multiply the movement vector by the time delta in the blueprint. Something like this:

[Image Removed]

  • In the PhysicsControlComponent asset, there are world origin positioned constraints (ie nearly every body of every actor is being pulled back towards 0,0,0). This is the view in the Chaos Visual Debugger

[Image Removed]I’m assuming that is unintentional? If so there are tick boxes in the PCC editor which you can uncheck to remove that.

[Image Removed]

There are a few other things which don’t seem right - but I wanted to check with you about what the actual intent is with the PCC?

Best

Geoff Stacey

Developer Relations

EPIC Games

[Attachment Removed]

Hello,

Apologies for the delay, I reached out to the team regarding the main questions above:

Why are the constraints so much less constrained with async physics on

If configured to run at the same or higher rate than the game thread this shouldn’t be the case. Async runs the exact same update at a fixed rate on another thread - it doesn’t run anything differently outside of the interpolator.

Why can a locked linear constraint stretch a bone? I thought the entire concept of a locked linear constraint (and not enabling any bone stretching of any kind) means this is physically impossible to happen?

No this is a misunderstanding of a joint, a locked linear constraint is not inviolable. If there are multiple constraints (joints or contacts) then we have to attempt to find an equilibrium between them. If that is impossible then some constraints will be violated. This is unavoidable if the constraint cannot be satisfied. If it can be satisfied but it wasn’t fully solved then more iterations will bring it closer to solved. You can enable projection on the joint, which will attempt to snap it back after the solve but this will have a number of side effects. It is entirely non-physical to project a joint and you will add a lot of energy into the system that will potentially destabilise the rest of the simulation - it’ll also probably look a bit odd just snapping it together but it might be worth a try.

Is there anything we can do to get the async physics working better just across the board? This is already 60hz physics vs the 30hz we’re targeting in the game so it’s already a more favourable situation than the real one for the physics

Async should be able to produce better simulations as it can run fixed tick. Are you doing any interaction with physics on the game thread? Like adding forces or velocities via BP? That can be a source of bad behaviour when using async physics as you need to reform all of your physics-affecting gameplay code to work only on the physics thread to make that work correctly

Regarding the setup in the example project:

This appears to be mostly quirks of general async physics rather than an issue with PCC.

The two characters in the example use a physics asset, where the first two “spines” are kinematic, and the last three are simulated. The CMC one uses a character movement component. The TesterNoSkeletalMove sets the actor location directly. It sets it with no sweep… arguably it should be swept, as otherwise the constraint target velocity should always be zero.

If the PCC setup is disconnected, then we see this.

[Image Removed]

The kinematic part of the character is in sync with the game (there’s a very short offset on the right-hand side of the first spine). However, the simulated part is coming from async physics - it looks like it’s exactly two frames behind (p.AsyncInterpolationMultiplier defaults to 2), since the actor/mover is moving really fast from left to right:

We don’t have any proper solution to this, with async physics. It’s inevitable that physics is de-synced, and if we tried to predict the physics to correct for the lag, it would be noisy.

So, as a poor alternative, PCC attempts to at least make any SKM that it is set up on consistent - i.e. kinematic and simulated bodies should come from the same source, and that is the physics state. Thus it calls BodyInstance->SetUpdateKinematicFromSimulation(…) You can choose true/false here in the body modifier, but it defaults to true.

That explains why the “stretching” gets shifted to the offset between the root and the actor when PCC is enabled:

[Image Removed](The reason that the second spine is simulated when PCC is enabled, is that the physics control asset explicitly sets that)

If you use async physics you cannot have the game thread making changes as the dt doesn’t match. The changes will make it over to the physics thread but not in the way you expect. A single impulse is usually fine, continuous movement is not. There’s also the async queue - that’s the 2 frames called out above. That’s controlled by p.AsyncInterpolationMultiplier which defaults to 2. If you’re not able to offload everything that’s gameplay affecting to the physics thread then async physics isn’t a viable option.

If you disable the Update Kinematic from Simulation setting on the PCC modifiers, then you see this - the same dislocation (but shifted to a different joint, as expected) as in the non-PCC case.

[Image Removed]By adjusting p.AsyncInterpolationMultiplier (how many frames back it should look for interpolation - defaults to 2) it’s possible to see that a big number like 5, will cause the stretching/dislocationto be worse because its reaching way back in time. The “ideal” value would be zero - but that would mean interpolating between the last async solve and the next one (in the future!). In practice, this just gives us the latest async result, which is still likely one frame behind.

[Attachment Removed]

Thanks Sam, if it’s OK I’ll go ahead and close this ticket.

[Attachment Removed]

Hi yeah, sorry these were just me getting something very rough together to show the issue. There are of course setup issues with this sample project but none of them explain the core issue to me which is the constraints being so much less constrained on async physics and the drastic different between async and non async physics.

I just tested again in the sample project with delta time on the movement (CMC already had it but I added it to the pure root moving BP), as well as disabling the world controls on all bones except Spine_004 and setting that world control to 100cm behind the object instead of the origin. We still get this crazy stretching with async physics on. Similar with the CMC [Image Removed]Compared to no async physics:

[Image Removed]

There’s a drastic difference in the quality of the constraints and where the physics controls are targeting with the non async one being almost touching the control and the async one the control is far ahead of the actor (due to the huge offset from root?): [Image Removed]

These are all with control strengths of 0.1 linear and angular, incredibly weak controls so it’s basically just drag causing this.

Here’s a shot with all world space controls created but not enabled, it still has an incredible difference in how the constraints are resolved on async physics and huge reduction in quality:

[Image Removed]

I guess my main questions here are:

  • Why are the constraints so much less constrained with async physics on (seemingly only when world space controls have been created even if not enabled?). Regardless of setup there’s a gigantic difference between async and non async physics just by ticking that one tickbox in the settings
  • Why can a locked linear constraint stretch a bone? I thought the entire concept of a locked linear constraint (and not enabling any bone stretching of any kind) means this is physically impossible to happen? It seems more like a relatively strong spring than a hard constraint, whereas with non async physics it acts more like a hard constraint
  • Is there anything we can do to get the async physics working better just across the board? This is already 60hz physics vs the 30hz we’re targeting in the game so it’s already a more favourable situation than the real one for the physics

I’ve also attached the updated project with world controls created but disabled in the PCA and movement including DT as per the very last screenshot.

[Attachment Removed]

Thank you for the in depth reply. There’s lots of little side bits in here we could go back and forth on but I think the core of this issue is it seems like there’s no current way to cleanly use both kinematic and simulated parts on the same mesh with async physics enabled. There’s a few cvars and various settings we can tweak to get partially there but no clean fix. I spent a few days trying all those various options before and couldn’t get anything good enough so I guess we’ll have to re-evaluate our options here

[Attachment Removed]