Chaos can not generate contact points while two dynamic convexes actually collide

After reviewing the relevant source code, I suspect that the issue may be caused by the current strategy used for selecting the contact plane during convex-convex collision manifold construction.

The convex-convex contact points are generated in the following function:

Function:​

template <typename ConvexImplicitType1, typename ConvexImplicitType2> void ConstructConvexConvexOneShotManifold

Location:​

Engine\Source\Runtime\Experimental\Chaos\Private\Chaos\CollisionOneShotManifolds.cpp

This function is responsible for building the collision manifold between two convex shapes in a “one-shot” manner. It internally calls:

Function:​

template <typename ConvexImplicitType> int32 SelectContactPlane(…)

to determine the “best” contact plane based on the separating axis identified by

GJKContactPointMargin.

However, the current implementation of SelectContactPlane selects the plane that has the closest normal alignment with the separating axis, without considering whether the selected plane actually overlaps with the other convex shape.

This can be problematic when a convex shape has multiple planes (faces) with similar or nearly parallel normals. In such cases, the current selection strategy may incorrectly pick a plane that is not truly involved in the contact, simply because its normal is closest to the separating axis.

As a result, if the selected contact plane does not actually overlap​ with the other convex, no clipped vertices will be generated during the clipping phase, and thus no valid contact points will be produced for that pair​ — even though a real collision or proximity might exist.

To illustrate the issue more clearly, I have recorded a video:

Video:

StepWithModifiedEngine_DrawSAT_DrawContactPlane.mp4

which shows, frame by frame, the selected separating axis and the corresponding contact planes that were chosen by the algorithm. The footage demonstrates that the selected plane may not align with the actual overlapping region between the two convexes.

Reproduction Steps

The issue can be reproduced using the original UE5.5.4​ engine.

(Note: The relevant Chaos collision detection code has not been significantly updated for nearly a year, so the latest UE5 versions may still be affected by the same issue.)

Steps to Reproduce:

  1. Open the level named “StoneCollisionTest”.
  2. Enter Play-In-Editor (PIE)​ mode.
  3. Open the in-game console​ and execute the following command: “p.Chaos.Solver.Collision.AllowManifoldUpdate 0” (:locked: This disables the reuse of contact manifolds across different frames, ensuring that contact points are not artificially stabilized by reusing old data)
  4. Move the camera​ (controlled by the player) to overlap with the trigger box located on your right side​ within the level.
  5. This action will cause two stone objects to reset to their initial state.
  6. Observe the behavior:​ In some cases, you will notice instability in the contact behavior​ — such as jittering, inconsistent contact forces, or unexpected collision responses.

:movie_camera: For a clear visual demonstration of this instability, please refer to the attached video: “CaseReproduction.mp4”, which captures the issue frame by frame.

Hi Jianlin,

Thank you for the detailed reproduction steps and project.

I created a bug report for this issue that can be tracked here if/when it’s approved for public visibility: Unreal Engine Issues and Bug Tracker (UE\-356457\). There is no ETA as priorities for bugs and features can shift at any time.

In the meantime, there’s this document that notes Reduce Jittering in collision resolution: avoid small faces on convex hulls. During collision resolution, Chaos only considers a single contact face from a convex hull per iteration. If it contains many tiny faces, the solver may switch between them frame to frame, we don’t get a stable contact manifold and introduces jitter.

Please let me know if this helps!

Thank you

Hello,

I wanted to follow-up and let you know that the public issue tracker is live, I’ll be closing out the case, but feel free to respond here if you have follow-up questions.

Thank you.