So I managed to put together something in BP and its C++ equivalent using your idea, sharing here in case it helps anyone:
void APlayerCharacter::HandleMovementInput(float X, float Y)
{
FVector Forward = GetActorForwardVector();
FVector Right = GetActorRightVector();
FVector InputVector = (Forward * Y + Right * X);
FVector InputDirection = InputVector.GetSafeNormal();
FVector CounterDirection;
FVector TraceStart = GetActorLocation();
FVector TraceEnd = GetActorLocation() + InputDirection * 100.0f;
FHitResult Hit;
FCollisionQueryParams Params;
Params.AddIgnoredActor(this);
bool bHit = GetWorld()->LineTraceSingleByChannel(Hit, TraceStart, TraceEnd, ECC_Visibility, Params);
if (bHit && Hit.bBlockingHit)
{
float Distance = (Hit.ImpactPoint - TraceStart).Size();
float Ratio = FMath::GetMappedRangeValueClamped(FVector2D(50.f, 200.f), FVector2D(0.f, 1.0f), Distance);
CounterDirection = (InputVector * (1.0f - Ratio)) * -1;
AddMovementInput(InputDirection + CounterDirection, 1.0f);
}
else
{
AddMovementInput(InputDirection, 1.0f);
}
// Debug
if (bDrawCollisionChecks)
{
DrawDebugLine(GetWorld(), TraceStart, TraceEnd, bHit ? FColor::Red : FColor::Green, false, .015f, 0, .5f);
if (bHit) DrawDebugPoint(GetWorld(), Hit.ImpactPoint, 50, FColor::Red, false, .015f);
}
}
It does works well to prevent basic clipping, but if you run into a wall and shake the mouse, you can still clip your head through. So if anyone has ideas to improve this, I’m all ears.