Description

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.

What happens

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.

What should happen

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.

Why it happens

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::SetupChaos/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 AdvanceClusteringPBDRigidClustering.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.

Have Comments or More Details?

There's no existing public thread on this issue, so head over to Questions & Answers just mention UE-392998 in the post.

0
Login to Vote

Unresolved
ComponentUE - Runtime - Simulation
Affects Versions5.8
CreatedAug 21, 2026
UpdatedAug 21, 2026
View Jira Issue