Tiny capsule component offset?

Hello everyone. I don’t know if this is the right place to post this but this is something that helped me.

I was running some tests trying to implement some gameplay functions based on modifying the capsule component’s height.
This usually ended in my character getting stuck in the ground.

During play in editor I unpossessed my pawn in order to check positions and check what was going on.

Turns out there is a tiny offset between the capsule component and the ground of about 0.15 units when standing idle and this number is constant in both examples I tried on (Shooter Game and First Person Template). I then simply added or subtracted this amount and everything worked correctly now. No jitter, no unsmooth transitions, no getting stuck in the ground. Anything more than 0.15 results in a tiny fall between states and anything less results in getting stuck. Weird.

Now, this is something I intend to not use in my code and find another way to fix my issues but maybe knowing that there is this distance will help you somehow.

I’m not sure what this tiny offset is for either, but it was present in UE3 too.

This small gap is there to prevent collisions as you slide across the ground or over seems between geometry. The code tries to maintain a range between 1.9 and 2.4 units (usually the average 2.15). I’m not sure why you are seeing 0.15 units instead.

If you use “displayall CharacterMovementComponent CurrentFloor” in the console in-game you will see FloorDist as part of that display.

I’m curious about why this is causing a problem for you. I’m not entirely clear about what you are doing-- shrinking and growing the capsule? That should be ok, but as you shrink it, you will be higher off the ground and could fall. This is dependent on both the floor offset and also MaxStepHeight, within which height you will snap to the ground if already walking.

Some more info on the steps you are taking and the undesirable results you’re seeing will help me diagnose your issue, if you could!

2 Likes

No worries on this, it is already fixed.

I was using a method to interpolate the capsule component size and move the actor down to compensate in order to crouch. I decided to try many different methods (some just as testing to get more used to Unreal Engine 4 c++), two of my tests being

A)Moving the actor down the same amount used when reducing the capsule’s half height
B)Ray tracing to check the amount to compensate based on capsule half height and distance to ground

Both resulted in the character getting stuck in the ground and this could be easily fixed by using Sweep with SetActorLocation(), but I wanted to check why the math wasn’t precise. In fact, it was because of this offset.

I measured it at 0.15 (0.147-0.152) by placing my character (or shooter game character) at a surface located at 0,0,0 (the actual collision, not the origin) and it always resulted at that number.

In the end I decided to make my own CharacterMovementComponent and Override the crouch functions. In case someone sees this, I have my own set of problems with that :smiley:

https://answers.unrealengine.com/questions/60441/character-movement-component-setfromsweep-linker-e.html

I have a workaround for that issue so it is not a big deal but anyways, any help would be appreciated.

Strange, I’m also using a custom crouch implementation and mine works perfectly.

I have an interpolation float that just runs from 0 (uncrouched) to 1 (fully crouched) and do the following calculations:



                // Calculate what our new dimensions must be
		float const newHeight = CharacterStats->GetTotalHeight() - CrouchInterpolator->GetInterpValue() * (CharacterStats->GetTotalHeight() - CharacterStats->GetCrouchHeight());
		float const newWidth = CharacterStats->GetTotalWidth() - CrouchInterpolator->GetInterpValue() * (CharacterStats->GetTotalWidth() - CharacterStats->GetCrouchWidth());
		
		FVector newLoc = GetActorLocation();

		// Calculate where our new location will be - Only adjust if we're on the ground
		if (CharacterMovement->IsMovingOnGround())
		{			
			newLoc.Z -= CapsuleComponent->GetScaledCapsuleHalfHeight() - newHeight * 0.5f;
		}

		if (CanIncreaseCollision(newWidth, newHeight, newLoc))
		{		
			SetActorLocation(newLoc);
			SetCharacterDimensions(newWidth, newHeight);				
		}




bool APWNPlayerCharacter::CanIncreaseCollision(float newWidth, float newHeight, FVector newLoc)
{
	// Collision params
	FCollisionQueryParams colQueryParams(NAME_None, false, this);	
	FCollisionObjectQueryParams colObjQueryParams;	
	
	// Capsule extent
	FVector extent;
	extent.X = newWidth * 0.5f;
	extent.Y = extent.X;
	extent.Z = newHeight * 0.5f;	
	
	return !(GetWorld()->OverlapTest(newLoc, FQuat::Identity, FCollisionShape::MakeCapsule(extent), colQueryParams, colObjQueryParams));
}




void APWNPlayerCharacter::SetCharacterDimensions(float NewWidth, float NewHeight)
{
	CapsuleComponent->SetCapsuleSize(NewWidth * 0.5f, NewHeight * 0.5f, true);
}


CharacterStats is just a container with some float values and the Get functions are accessors.