Search code examples
c++unreal-engine42d-games

Deflection issue in platformer game programmed with Unreal Engine 4


I'm trying to program a simple platformer game with very accurate movement using Unreal Engine 4 (4.22 release). It took some inspiration from games like Super Meat Boy or Celeste. I'm using the APaperCharacter that uses UCharacterMovementComponent, but I'm not very satisfied of it. Particularly I would like to avoid the deflection that is used in UCharacterMovementComponent::PhysFalling() method:

const FVector OldHitNormal = Hit.Normal;
    const FVector OldHitImpactNormal = Hit.ImpactNormal;        
    FVector Delta = ComputeSlideVector(Adjusted, 1.f - Hit.Time, OldHitNormal, Hit);

    // Compute velocity after deflection (only gravity component for RootMotion)
    if (subTimeTickRemaining > KINDA_SMALL_NUMBER && !bJustTeleported)
    {
      const FVector NewVelocity = (Delta / subTimeTickRemaining);
      Velocity = HasAnimRootMotion() && !CurrentRootMotion.HasOverrideVelocity() ? FVector(Velocity.X, Velocity.Y, NewVelocity.Z) : NewVelocity;
    }

I recorded a video to show you the behavior I would like to prevent:

https://www.youtube.com/watch?v=fko1aPl-Vdo

I'm thinking to create my personal movement component that derives UCharacterMovementComponent in order to override the ComputeSlideVector() method, but I don't know if it is the best idea to resolve this issue. I would like to have your opionion and I would like to know if I can simply solve the problem changing some parameters by editor.


Solution

  • I eventually decided to create my own class derived from UCharacterMovementComponent. I solved the issue I described in my question overriding the UCharacterMovementComponent ::ComputeSlideVector() method:

    FVector UMyMovementComponent::ComputeSlideVector(const FVector& Delta, const float Time, const FVector& Normal, const FHitResult& Hit) const
    {
        FVector Result = Super::ComputeSlideVector(Delta, Time, Normal, Hit);
    
        if (Hit.bBlockingHit)
        {
            float Angle = FVector::DotProduct(Hit.Normal, FVector::DownVector);
            if (Angle > KINDA_SMALL_NUMBER) // if the collision normal points downwards
            {
                Result.X = 0.0f;
            }
        }
    
        return Result;
    }