A geometry collection with One Way Interaction Level set to 0 never breaks from its own collisions. It falls, lands, and stays intact no matter what it hits. Set the level to -1 (feature off) and change nothing else, and the same collection breaks on impact as expected.
—
The collection lands and never breaks. It receives zero OnChaosBreakEvent callbacks and its root stays unbroken indefinitely. It comes to rest at the same height as an identical non-one-way collection, so the collision is definitely happening — it just produces no damage.
This is independent of what it lands on ie A one-way collection also cannot be broken by another collection dropped onto it.
—
It should break, identically to the control.
One-way interaction is documented as stopping a body from applying forces to non-one-way bodies. It should suppress the damage a one-way body deals to others; it should not suppress the damage it receives, and it should not stop the body breaking itself on impact.
—
FRigidClustering::ComputeStrainFromCollision discards every one-way contact before any strain is accumulated — Chaos/Private/Chaos/PBDRigidClustering.cpp:2240:
if (ContactHandle->GetContact().GetIsOneWayInteraction())
{
continue;
}
The flag it tests is set in FPBDCollisionConstraint::Setup — Chaos/Private/Chaos/Collision/PBDCollisionConstraint.cpp:351:
Flags.bIsOneWayInteraction = (bDynamic0 || bDynamic1) && (bOneWay0 || bOneWay1);
That is true for any contact where at least one body is dynamic and at least one is one-way. It never asks what the other body is, so it cannot distinguish "one-way damaging a non-one-way body" (which should be suppressed) from "one-way body being damaged by anything at all" (which should not). The bDynamic term only excludes static/kinematic-vs-static/kinematic pairs, which carry no impulse anyway. That is why the counterpart type above makes no difference.
With level 0, FGeometryCollectionPhysicsProxy marks every particle one-way, cluster root included — GeometryCollectionPhysicsProxy.cpp:1753:
const bool bIsOneWayInteraction = (Parameters.OneWayInteractionLevel >= 0) && (Level[ParticleIndex] >= Parameters.OneWayInteractionLevel);
So CollisionImpulses() stays at 0 for the whole collection, and the release test in AdvanceClustering — PBDRigidClustering.cpp:1178 — never fires:
const FRealSingle MaxAppliedStrain = FMath::Max(Child->CollisionImpulses(), Child->GetExternalStrain());
if ((MaxAppliedStrain >= Child->GetInternalStrains()) || bForceRelease)
Only the first term is affected — externally applied strain still breaks the collection normally.
There's no existing public thread on this issue, so head over to Questions & Answers just mention UE-392998 in the post.
| 0 |
| Component | UE - Runtime - Simulation |
|---|---|
| Affects Versions | 5.8 |
| Created | Aug 21, 2026 |
|---|---|
| Updated | Aug 21, 2026 |