Better Surface Orientation
Surface collision inside geometry
There is a slight problem with the ComputeSurfaceInfo() function such that sometimes when there are very close or overlapping geometry the character has an incorrect rotation.

The reason for this is that the shape sweep we are using is happening from within the geometry.
Even though the Shape Sweep is technically colliding with the "top edge of the object under the higher one" it doesn't make visible sense.

More visually accurate collision
It would make much more visible sense if we did the collision starting from the player then reaching out to see what we collide with first, which would be the "side face of the object higher up" the same as the other collision .

Luckily we don't have to change anything about the Shape Sweep, as it is still a very good way of detecting multiple simultaneous collisions, however we just need to do a little extra when adding up the surface normals.
Extra Sweep per collision
Since we can't trust the hits from our Shape Sweep to be visually correct, we'll perform an additional smaller sweep from the player to the collision point to check if we should visually collide with anything before the original hit.
If we do, then that means we should take that surface's normal when collecting the normals instead

Doing a raw raycast might still produce the issue because of how thin it would be, so instead we'll use another small Shape Sweep.
.cpp
// ZCCharacterMovementComponent.cpp
void UZCCharacterMovementComponent::ComputeSurfaceInfo()
{
// ...
const FVector Start = UpdatedComponent->GetComponentLocation();
const FCollisionShape CollisionShape = FCollisionShape::MakeSphere(6); //reasonably smol sphere
for (const FHitResult& WallHit : CurrentWallHits)
{
const FVector End = Start + (WallHit.ImpactPoint - Start).GetSafeNormal() * 120; //magic number here is just making sure we make it to the surface
FHitResult AssistHit;
GetWorld()->SweepSingleByChannel(AssistHit, Start, End, FQuat::Identity, ECC_WorldStatic, CollisionShape, ClimbQueryParams);
CurrentClimbingPosition += AssistHit.ImpactPoint;
CurrentClimbingNormal += AssistHit.Normal;
}
// ...
}

Last updated