Why do multiple overlaps trigger with USkeletalMeshComponent and UPrimitiveComponent when both are moving?

Create A as a parent has B & C as children, B is a SkeletalMesh and C is a static mesh and both movable.
Invoke A.AddMovementInput each tick to make A always moving
Move B to overlap C, then every frame B will fire BeginOverlap And EndOverlap with C。over and over.

Notice that the relative location between B and C is not changed and still overlap each other,so expected result IMO is that EndOverlap won’t be invoked.

After investigating the source code,I found that:

bool UPrimitiveComponent::ComponentOverlapMultiImpl(TArray<struct FOverlapResult>& OutOverlaps, const UWorld* World, const FVector& Pos, const FQuat& Quat, ECollisionChannel TestChannel, const struct FComponentQueryParams& Params, const struct FCollisionObjectQueryParams& ObjectQueryParams) const
	FComponentQueryParams ParamsWithSelf = Params;
	return BodyInstance.OverlapMulti(OutOverlaps, World, /*pWorldToComponent=*/ nullptr, Pos, Quat, TestChannel, ParamsWithSelf, FCollisionResponseParams(GetCollisionResponseToChannels()), ObjectQueryParams);

bool USkeletalMeshComponent::ComponentOverlapMultiImpl(TArray<struct FOverlapResult>& OutOverlaps, const UWorld* World, const FVector& Pos, const FQuat& Quat, ECollisionChannel TestChannel, const struct FComponentQueryParams& Params, const struct FCollisionObjectQueryParams& ObjectQueryParams) const

	if (!Bodies.IsValidIndex(RootBodyData.BodyIndex))
		return false;

	const FTransform WorldToComponent(ComponentToWorld.Inverse());
	const FCollisionResponseParams ResponseParams(GetCollisionResponseToChannels());

	FComponentQueryParams ParamsWithSelf = Params;

	bool bHaveBlockingHit = false;
	for (const FBodyInstance* Body : Bodies)
		if (Body->OverlapMulti(OutOverlaps, World, &WorldToComponent, Pos, Quat, TestChannel, ParamsWithSelf, ResponseParams, ObjectQueryParams))
			bHaveBlockingHit = true;

	return bHaveBlockingHit;

When calling Body->OverlapMulti,UPrimitiveComponent not use WorldToComponent like USkeletalMeshComponent does,which results at

bool FBodyInstance::OverlapMulti(TArray<struct FOverlapResult>& InOutOverlaps, const class UWorld* World, const FTransform* pWorldToComponent, const FVector& Pos, const FQuat& Quat, ECollisionChannel TestChannel, const struct FComponentQueryParams& Params, const struct FCollisionResponseParams& ResponseParams, const struct FCollisionObjectQueryParams& ObjectQueryParams) const

	if ( !IsValidBodyInstance()  && (!WeldParent || !WeldParent->IsValidBodyInstance()))
		UE_LOG(LogCollision, Log, TEXT("FBodyInstance::OverlapMulti : (%s) No physics data"), *GetBodyDebugName());
		return false;

	bool bHaveBlockingHit = false;

	// Determine how to convert the local space of this body instance to the test space
	const FTransform ComponentSpaceToTestSpace(Quat, Pos);

	FTransform BodyInstanceSpaceToTestSpace;
	if (pWorldToComponent)
		const FTransform RootTM = WeldParent ? WeldParent->GetUnrealWorldTransform() : GetUnrealWorldTransform();
		const FTransform LocalOffset = (*pWorldToComponent) * RootTM;
		BodyInstanceSpaceToTestSpace = ComponentSpaceToTestSpace * LocalOffset;
		BodyInstanceSpaceToTestSpace = ComponentSpaceToTestSpace;

They use the different BodyInstanceSpaceToTestSpace.
To be more clear, A.AddMovementInput will result in USceneComponent::MoveComponentImpl.
USceneComponent::MoveComponentImpl will first InternalSetWorldLocationAndRotation to set B and C’s component transform recursively. And then will update BodyInstance.SetBodyTransform to invoke PRigidDynamic->setKinematicTarget(PNewPose),which will result in a velocity that will move the body into the desired pose,that means at this frame, B&C’s PRigidDynamic are still not changed.
But when checking overlaping, C(UPrimitiveComponent) is using the component location(rendering location,have updated to new position), B(USkeletalMeshComponent) uses GetUnrealWorldTransform to get location, which takes physics body’s location, which remains at last frame.

So OverlapMulti failed and trigger a EndOverlap.
And WeldParent seems seems not working.

It’s a little complicated and I’m a new UE learner,hope it helps to make it better.

Hey -

If possible could you provide a more detailed explanation of your setup? I tried creating a new Character class (A) and giving it a skeletal mesh component and a static mesh component (B and C). I set both components to Moveable with SetMobility and call AddMovementInput on Tick. When I make a blueprint of this class, the skeletal mesh and static mesh are overlapping each other by default. After adding an instance of the blueprint to the level, neither the skeletal mesh nor static mesh appear to be triggering any begin/end overlaps. Please let me know how you’ve setup your components and exactly what you’re doing in code / blueprints.

I use BP.
Your setup is a little different.
My concrete use case is:
A is a static mesh, like a ship. with FloatPawingMovement
B is a character(skeletal mesh, IMPORTANT) standing on the ship.
C is a static mesh(IMPORTANT), like a box on a ship.
B & C are both A’s child actor component.

then in A’s BP, I invoke A.AddMovementInput every tick.
Use keyboard to Move B to overlap C.

I created a first person demo project and modified it a little to show the case.
Attached with my demo project:
(default attachment is too small.use onedrive to share it.)
Use WASD to move arms to overlap the wall. at some position, overlaping events are not stable. over and over again.
[link text][1]

And the screenshot

Hey -

I took at look at the project you provided and noticed that the pawn being used as the child actor has no capsule collision which is normally used for collision in characters. The skeletal mesh asset has a physics asset associated with it that you can add collision to instead if needed. The following post gives an detailed explanation as well as a link to video tutorials on using the physics asset tool (PhAT).


Thanks for your patient!
Have the post above, but I don’t think the problem is about my skeletal mesh. The arms comes from starter content and have “SK_Mannequin_Arms_PhysicsAsset” with it, so it’s physics works well actually.
And I don’t think character’s capsule collision matters here. I just don’t need character itself’s collision and just only demonstrate the arms skeletal mesh collision to show you the problems.

Looking at the documentation for FloatingPawnMovement it mentions:

“During swept (non-teleporting) movement only collision of UpdatedComponent is considered, attached components will teleport to the end location ignoring collision.”

With this in mind, making the skeletal mesh component the root component of TestPawn and setting it’s collision to BlockAll instead of OverlapAll causes the mesh to correctly collide with the box mesh.

To make it simpler.
Even if I removed the FloatingPawnMovement


And make move with the most simplest way:


But SkeletalMesh must set collision to OverlapAll to generate overlap events.
BlockAll won’t generate overlap events here.
So I don’t think FloatingPawnMovement is the problem.

Can you explain what you are trying to accomplish? Your title indicates that collision isn’t working for the skeletal mesh / primitive. If you have OverlapAll, there is no collision occurring since they are overlapping rather than colliding. At this point I’m not sure I understand what the issue is that you’re having/reporting.

Sorry for my confusing title.
My problem is WHY overlapping events between skeletal mesh and primitive would happens multiple times even though I keep the relative position of two not changed.
I think it suppose to be only one BeginOverlap and only one EndOverlap.