Search code examples
c++game-developmentunreal-engine4unreal-engine5

Air control for mouse movement to change direction mid-air after jumping


I'm working on a custom character in Unreal Engine 5. I want the player to have his velocity direction based on mouse movement when he is in the air.

For example, when you jump forward and move your mouse right, he should follow the new direction, but if you jump backwards and move your mouse right, it will change direction towards where your back is looking.


Solution

  • I created a custom character movement component and overrode CalcVelocity() method:

    // AirControl = 0;
    // AirControlBoostMultiplier = 0;
    // AirControlBoostVelocityThreshold = 0;
    
    void UCustomCharacterMovementComponent::CalcVelocity(const float DeltaTime, const float Friction, const bool bFluid, const float BrakingDeceleration)
    {
        Super::CalcVelocity(DeltaTime, Friction, bFluid, BrakingDeceleration);
    
        if (IsMovingOnGround() && Velocity.Size() > 0) {
            const FVector NewDirection = UKismetMathLibrary::InverseTransformDirection(GetActorTransform(), Velocity);
            LastYawOnGround = FMath::CeilToInt(FRotationMatrix::MakeFromX(NewDirection).Rotator().Yaw);
        }
    
        // Air control for mouse movement to change direction mid-air after jumping
        if (!IsMovingOnGround()) {
            FVector VelocityDirection;
            const bool IsMovingForward = UKismetMathLibrary::InRange_IntInt(LastYawOnGround, -22, 0) || UKismetMathLibrary::InRange_IntInt(LastYawOnGround, 0, 22);
            const bool IsMovingForwardRight = UKismetMathLibrary::InRange_IntInt(LastYawOnGround, 23, 67);
            const bool IsMovingRight = UKismetMathLibrary::InRange_IntInt(LastYawOnGround, 68, 112);
            const bool IsMovingBackwardRight = UKismetMathLibrary::InRange_IntInt(LastYawOnGround, 113, 157);
            const bool IsMovingBackward = UKismetMathLibrary::InRange_IntInt(LastYawOnGround, -180, -158) || UKismetMathLibrary::InRange_IntInt(LastYawOnGround, 158, 180);
            const bool IsMovingBackwardLeft = UKismetMathLibrary::InRange_IntInt(LastYawOnGround, -157, -113);
            const bool IsMovingLeft = UKismetMathLibrary::InRange_IntInt(LastYawOnGround, -112, -68);
            const bool IsMovingForwardLeft = UKismetMathLibrary::InRange_IntInt(LastYawOnGround, -67, -23);
    
            if (IsMovingForward) {
                VelocityDirection = UpdatedComponent->GetForwardVector();
            } else if (IsMovingBackward) {
                VelocityDirection = -UpdatedComponent->GetForwardVector();
            } else if (IsMovingRight) {
                VelocityDirection = UpdatedComponent->GetRightVector();
            } else if (IsMovingLeft) {
                VelocityDirection = -UpdatedComponent->GetRightVector();
            } else {
                if (IsMovingForwardRight) {
                    VelocityDirection = UpdatedComponent->GetForwardVector() + UpdatedComponent->GetRightVector();
                } else if (IsMovingForwardLeft) {
                    VelocityDirection = UpdatedComponent->GetForwardVector() - UpdatedComponent->GetRightVector();
                } else if (IsMovingBackwardRight) {
                    VelocityDirection = UpdatedComponent->GetRightVector() - UpdatedComponent->GetForwardVector();
                } else if (IsMovingBackwardLeft) {
                    VelocityDirection = -(UpdatedComponent->GetForwardVector() + UpdatedComponent->GetRightVector());
                }
                
                VelocityDirection = UKismetMathLibrary::Normal(VelocityDirection / 2);
            }
    
            Velocity -= Velocity - VelocityDirection * Velocity.Size();
        }
    }