UMovementComponent::OverlapTest接口在开启bTraceComplex后,Overlap检测不到完全包含关系的碰撞

UMovementComponent::OverlapTest接口在开启bTraceComplex后,Overlap检测不到完全包含关系的碰撞

[Attachment Removed]

Steps to Reproduce
UMovementComponent::OverlapTest接口在开启bTraceComplex后,Overlap检测不到完全包含关系的碰撞

下面这个绿色胶囊体完全被包含在白色box碰撞体内,在开启bTraceComplex后,UMovementComponent::OverlapTest检测不到overlap,返回值是0(图中绿色胶囊体上面的字符指示)

[Image Removed]

[Attachment Removed]

Hello [mention removed]​,

I wanted to confirm that I have reproduced the issue you reported with UMovementComponent::OverlapTest not detecting overlaps correctly when bTraceComplex is enabled. I followed the repro steps you provided, and the issue occurs in UE 5.7.1 (Launcher).

Additionally, I’ve confirmed that the issue persists in a recent source build from main (CL 48883915).

I will continue investigating and will follow up with more information soon.

Best,

Francisco

[Attachment Removed]

Hello [mention removed]​,

I did a deeper investigation into how this is handled internally and wanted to share some additional context.

When Trace Complex on Move is enabled on a primitive component, movement-related queries explicitly switch from using simple collision bounds to tracing against complex collision geometry (per-triangle). This is stated directly in the property definition:

/**
 * If true, component sweeps with this component should trace against complex collision during movement
 * (for example, each triangle of a mesh).
 * If false, collision will be resolved against simple collision bounds instead.
 */
uint8 bTraceComplexOnMove : 1;

This setting is propagated into the scene query parameters during movement and from there, the query flows into Chaos, where enabling bTraceComplex results in filtering against shapes marked for complex collision. In Chaos, this distinction is explicit via filter flags such as:

// CollisionFilterData.h
 
SimpleCollision = 0b00000001,	// The shape is used for simple collision
ComplexCollision	= 0b00000010,	// The shape is used for complex (trimesh) collision

This explains the difference in results you’re observing. When simple collision is used, overlap checks operate on solid convex volumes, so a capsule fully contained inside a box is correctly reported as overlapping. When complex collision is used, the geometry is treated as a triangle surface. If the capsule is fully inside the mesh without intersecting any triangles, there is no surface intersection to report, and the overlap test can return false. Once the capsule intersects or touches the surface, the query returns true.

Based on this, the behavior appears to be intended and consistent with how Trace Complex on Move and Chaos simple versus complex collision are designed, rather than an engine defect.

Please let me know if this information helps your case.

Best,

Francisco

[Attachment Removed]

Many thanks for your reply. I agree with your analysis for the issue, but I still think this is a bug, not a feature. From the perspective of the interface user, he may not care whether it is TraceComplex or TraceSimple. In deed, what he cares about is whether the character has intersect with the scene collision shape. If the capsule is fully inside the mesh collision shape without intersecting any triangles, In this situation, the character is obviously considered overlapping with the mesh collision too. From this perspective, the interface user cannot use this interface to achieve his purpose. What’s worse more is that there is no feasible alternative.

[Attachment Removed]

I have tried using World->OverlapMultiByChannel or World->OverlapBlockingTestByChannel directly, and the result was the same. As long as FCollisionQueryParams ‘s bTraceComplex is set to true, when the capsule is completely contained within the scene collider, then the overlap testing cannot detect anything. For our needs, we must use Complex Trace to ensure accurate collision, that is the key problem.

In complex collision test, the scene collider is treated as a set of triangles without considering the volume region enclosed by the triangles. so overlap test return false。

This may be a very hard problem in Geometry

[Attachment Removed]

Thanks Francisco,

Hi there,

I’ve taken a look into this, and Fransico is correct that the scene query itself is using the Complex mesh - which is a TriMesh (and hence has no concept of volume). In order for this to understand containment, it needs to have a volumetric type of shape. Most of the time this would be a Convex Hull, but can also be an aggregate of more simple shapes.

The Complex geometry is always a TriMesh since it comes from the rendering side. For what you need, I’d suggest that you change the setting to “UseSimpleAsComplex” for the assets which you need the more accurate collision on, and use a curated set of convex meshes (or other implicit geometry).

All the best

Geoff Stacey

Developer Relations

EPIC Games

[Attachment Removed]

Hello [mention removed]​,

CharacterMovementComponent::OverlapTest evaluates overlaps using the movement component’s collision settings, including flags such as Trace Complex on Move. As a result, its behavior is tightly coupled to character movement, rather than being a general-purpose world overlap check. I agree the naming can be misleading in this context, but the function is primarily intended to support movement-related overlap validation.

To better understand your use case, can you confirm whether you want to perform an overlap check using a custom capsule placed at an offset location (i.e., not the character’s own capsule, like in your image).

If that is the intent, it may be more appropriate to issue a world overlap query directly, where the collision shape and query parameters are fully under your control. For example, I tested the following approach, testing overlap with a capsule with an offset from the player character:

UWorld* World = GetWorld();
if (!World)
{
	return;
}
 
// Create a capsule from an offset position relative to the character
const FVector CharacterLocation = GetActorLocation();
const FQuat   CharacterRotation = GetActorQuat();
const FVector TestLocation = CharacterLocation + Offset;
FCollisionShape CollisionShape = FCollisionShape::MakeCapsule(CapsuleRadius, CapsuleHalfHeight);
 
const ECollisionChannel QueryChannel = ECC_Visibility;
 
FCollisionQueryParams Params(SCENE_QUERY_STAT(WorldQueryTest), false);
Params.AddIgnoredActor(this);
 
// Perform the overlap test
TArray<FOverlapResult> Hits;
const bool bAny = World->OverlapMultiByChannel(
	Hits,
	TestLocation,
	FQuat::Identity,
	QueryChannel,
	CollisionShape,
	Params
);
 
// Log result
if (bAny)
{
	UE_LOG(LogTemp, Warning, TEXT("Overlap detected at location: %s (Candidates=%d)"),
		*TestLocation.ToString(), Hits.Num());
}
else
{
	UE_LOG(LogTemp, Warning, TEXT("No overlap at location: %s (Candidates=%d)"),
		*TestLocation.ToString(), Hits.Num());
}

In this case, the collision shape can be configured as needed, and bTraceComplex is explicitly set to false.

Please let me know if this aligns with your intended use case.

Best,

Francisco

[Attachment Removed]

Hello [mention removed]​,

Thanks for the follow up. You’re correct, there is no current built-in way for a complex overlap query to report pure containment when the capsule is fully inside a mesh without intersecting its surface. I agree supporting this goes beyond a simple workaround.

At this point, I’m going to escalate this to Epic so the engine team can evaluate whether this kind of functionality can be supported specifically for UMovementComponent::OverlapTest and complex collision queries.

Best,

Francisco

[Attachment Removed]