Character clipping through walls (Game Animation Sample)

Hello everyone,

I’m experimenting with the Game Animation Sample Project and playing around with how Motion Matching and GASP behave in different setups. I’ve managed to get a decent first-person mode working, but I’m having trouble with wall collisions.

The issue is that when the character runs into a wall, the head (and thus the camera) clips through it, which obviously breaks the experience in first person.

To try to fix it, I implemented some logic in C++ using GetWorld()->SweepSingleByChannel to run a set of sphere traces around the character. The idea was to detect nearby obstacles and cancel movement input when hitting a wall, based on the impact normals. It does detect obstacles and partially blocks movement, but the results don’t feel very natural — the character still leans slightly into walls and doesn’t convincingly stop.

Has anyone run into the same issue, or found a better way to prevent this kind of clipping when using GASP and motion matching in first-person?

Thanks in advance!

Hey @EarthCK!

Instead of checking for nearby obstacles, you can check if the character is about to hit an obstacle using the movement vector.

Check out this post of mine to see how :blush:

(Also see my following posts under the same topic)

Hope this helps! :innocent:

1 Like

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.