The Impact Point position returned by capsule collision is incorrect. Can anyone explain why?

I’m making a character climbing system. When the character is in climbing mode, I generate a collision-detecting capsule in front of the character at every tick and sweep forward one unit distance to continuously detect wall collisions and handle the climbing problem of the character movement component.

In order to facilitate observation, I used a transparent wall for the character to climb, and drew a white detection capsule and a yellow Impact Point.

[image]
Normal Climbing
[When the character climbs normally, the Impact Point detected by the capsule is directly in front of the character capsule.]

Although the character can already start climbing up the wall, the problem is that when the character climbs and moves somewhere on a flat wall vertical to the ground, the Impact Point position in the HitResult structure returned by capsule collision detection sometimes changes. It’s very weird (as shown in the picture, the yellow point represents the Impact Point). This incorrect Impact Point leads to the incorrect Impact Normal (affecting the rotation direction of my character when climbing). Can someone tell me this? Why?

Issue Climbing

Here is my code:

‘’'cpp

void UALCMovementClimbObject::SweepAndStoreWallHits()
{
const FALCMovementClimbCondition& currentConditionSettings = GetCurrentClimbModeDA()->ClimbConditionSettings;

const FCollisionShape CollisionShape = FCollisionShape::MakeCapsule(currentConditionSettings.ClimbCapsuleTraceRadius,currentConditionSettings.ClimbCapsuleTraceHalfHeight);
const FVector StartOffset = ALCMovementComp->UpdatedComponent->GetForwardVector() * currentConditionSettings.CapsuleTraceStartOffset;
const FVector Start = ALCMovementComp->UpdatedComponent->GetComponentLocation() + FVector(0,0,currentConditionSettings.CapsuleTraceVerticalOffset) + StartOffset; 
const FVector End = Start + ALCMovementComp->UpdatedComponent->GetForwardVector();	// Avoid using the same Start/End location for a Sweep, as it doesn't trigger hits on Landscapes.

TArray<FHitResult> Hits;
bool HitWall = false;
HitWall= UKismetSystemLibrary::CapsuleTraceMultiForObjects(
	GetWorld(),
	Start,
	End,
	currentConditionSettings.ClimbCapsuleTraceRadius,
	currentConditionSettings.ClimbCapsuleTraceHalfHeight,
	currentConditionSettings.ClimbableObjectTypes,
	false,
	TArray<AActor*>(),
	EDrawDebugTrace::ForOneFrame,
	Hits,
	true
	);
	
if(ALCMovementComp->DebugRules.bEnableClimbObjectDebug)
{
	if (CollisionShape.IsCapsule())
	{
		float CapsuleRadius = CollisionShape.GetCapsuleRadius();
		float CapsuleHalfHeight = CollisionShape.GetCapsuleHalfHeight();

		DrawDebugCapsule(
			GetWorld(),
			Start,
			CapsuleHalfHeight,
			CapsuleRadius,
			FQuat::Identity,
			FColor::White,   
			false,           
			0.f,
			0,
			1
		);
		DrawDebugCapsule(
			GetWorld(),
			End,
			CapsuleHalfHeight,
			CapsuleRadius,
			FQuat::Identity,
			FColor::White,    
			false,           
			0.f,
			0,
			1
		);
	}
	if(HitWall)
	{
		for(auto x:Hits)
		{
			DrawDebugPoint(GetWorld(),x.ImpactPoint,15,FColor::Yellow,false,0,0);
			DrawDebugPoint(GetWorld(),x.Location,15,FColor::Orange,false,0,0);
			DrawDebugDirectionalArrow(GetWorld(),Start, x.Location,1.5,FColor::Purple,false,0,0,1);
		}
	}
}
ClimbableSurfacesTracedResults = HitWall ? Hits : TArray<FHitResult>();

}
‘’’

Fixed, it turns out I was wrong when doing Computes Normal.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.