I’m using ACharacter class for a 2D platformer game. When the pawn (the main character) starts to jump form a ledge, it’s not able to land in the same position. I attached a video to show you what I mean:
The PerchRadiusThreshold parameter is set to 0 and CanWalkOffLedges is set to true. How can I change the behavior of the character when it lands in these situations?
I fixed this issue overriding UMovementComponent::GetPenetrationAdjustment() method:
FVector UPlatformCharacterMovementComponent::GetPenetrationAdjustment(const FHitResult& Hit) const
{
FVector Result = FVector::ZeroVector;
if (Hit.bStartPenetrating)
{
if (const auto* CapsuleComponent = CharacterOwner->GetCapsuleComponent())
{
float HalfHeight = CapsuleComponent->GetScaledCapsuleHalfHeight();
FVector BaseLocation = Hit.Location + (HalfHeight * FVector::DownVector);
if (Hit.ImpactPoint.Z >= BaseLocation.Z)
{
if (Hit.ImpactPoint.Z <= (BaseLocation.Z + HalfHeight))
{
Result = FVector::UpVector * (Hit.ImpactPoint.Z - BaseLocation.Z);
// since we're overriding the UMovementComponent::GetPenetrationAdjustment implementation
// then here we must execute the implementation of UCharacterMovementComponent::GetPenetrationAdjustment (afeter call to its Super class)
if (CharacterOwner)
{
const bool bIsProxy = (CharacterOwner->GetLocalRole() == ROLE_SimulatedProxy);
float MaxDistance = bIsProxy ? MaxDepenetrationWithGeometryAsProxy : MaxDepenetrationWithGeometry;
if (Hit.HitObjectHandle.DoesRepresentClass(APawn::StaticClass()))
{
MaxDistance = bIsProxy ? MaxDepenetrationWithPawnAsProxy : MaxDepenetrationWithPawn;
}
Result = Result.GetClampedToMaxSize(MaxDistance);
}
}
}
}
}
if (Result.IsZero())
{
// we execute the Super implementation because the overriden implementation has not been executed
Result = Super::GetPenetrationAdjustment(Hit);
}
return Result;
}