Air control now works with all gravity directions and fix rotations when changing grav

This commit is contained in:
Kevin Poretti 2023-01-07 22:46:30 -05:00
parent 8d8b7fa88c
commit bd20b78a3b
4 changed files with 107 additions and 7 deletions

Binary file not shown.

View File

@ -73,9 +73,9 @@ void UGSCharacterMovementComponent::PhysFalling(float deltaTime, int32 Iteration
{
// Acceleration = FallAcceleration for CalcVelocity(), but we restore it after using it.
TGuardValue<FVector> RestoreAcceleration(Acceleration, FallAcceleration);
Velocity.Z = 0.f;
IsCharacterUpAlignedToWorldUp() ? Velocity.Z = 0.f : Velocity.Y = 0.f;
CalcVelocity(timeTick, FallingLateralFriction, false, MaxDecel);
Velocity.Z = OldVelocity.Z;
IsCharacterUpAlignedToWorldUp() ? Velocity.Z = OldVelocity.Z : Velocity.Y = OldVelocity.Y;
}
}
@ -662,7 +662,11 @@ bool UGSCharacterMovementComponent::IsCharacterUpAlignedToWorldUp() const
void UGSCharacterMovementComponent::SetCharacterUpDirection(FVector NewUpDirection)
{
NewUpDirection.Normalize();
CharacterUpDirection = NewUpDirection;
if(!(CharacterUpDirection.Dot(NewUpDirection) > UE_KINDA_SMALL_NUMBER))
{
CharacterUpDirection = NewUpDirection;
SetMovementMode(MOVE_Falling);
}
}
FVector UGSCharacterMovementComponent::ConstrainInputAcceleration(const FVector& InputAcceleration) const
@ -792,6 +796,99 @@ void UGSCharacterMovementComponent::OnMovementModeChanged(EMovementMode Previous
ensureMsgf(GetGroundMovementMode() == MOVE_Walking || GetGroundMovementMode() == MOVE_NavWalking, TEXT("Invalid GroundMovementMode %d. MovementMode: %d, PreviousMovementMode: %d"), GetGroundMovementMode(), MovementMode.GetValue(), PreviousMovementMode);
}
void UGSCharacterMovementComponent::PhysicsRotation(float DeltaTime)
{
if (!(bOrientRotationToMovement || bUseControllerDesiredRotation))
{
return;
}
if (!HasValidData() || (!CharacterOwner->Controller && !bRunPhysicsWithNoController))
{
return;
}
FRotator CurrentRotation = UpdatedComponent->GetComponentRotation(); // Normalized
CurrentRotation.DiagnosticCheckNaN(TEXT("CharacterMovementComponent::PhysicsRotation(): CurrentRotation"));
FRotator DeltaRot = GetDeltaRotation(DeltaTime);
DeltaRot.DiagnosticCheckNaN(TEXT("CharacterMovementComponent::PhysicsRotation(): GetDeltaRotation"));
FRotator DesiredRotation = CurrentRotation;
if (bOrientRotationToMovement)
{
DesiredRotation = ComputeOrientToMovementRotation(CurrentRotation, DeltaTime, DeltaRot);
}
else if (CharacterOwner->Controller && bUseControllerDesiredRotation)
{
DesiredRotation = CharacterOwner->Controller->GetDesiredRotation();
}
else if (!CharacterOwner->Controller && bRunPhysicsWithNoController && bUseControllerDesiredRotation)
{
if (AController* ControllerOwner = Cast<AController>(CharacterOwner->GetOwner()))
{
DesiredRotation = ControllerOwner->GetDesiredRotation();
}
}
else
{
return;
}
if (ShouldRemainVertical())
{
FString DebugDesiredRotation = FString::Printf(TEXT("Desired Rotation: %s"), *DesiredRotation.ToString());
GEngine->AddOnScreenDebugMessage(-1, 0.0f, FColor::Cyan, DebugDesiredRotation);
DesiredRotation.Pitch = IsCharacterUpAlignedToWorldUp() ? 0.f : FRotator::NormalizeAxis(DesiredRotation.Pitch);
DesiredRotation.Yaw = IsCharacterUpAlignedToWorldUp() ? FRotator::NormalizeAxis(DesiredRotation.Yaw) : 0.f;
float Rot = 0.0f;
if(CharacterUpDirection.Dot(FVector::DownVector) > UE_KINDA_SMALL_NUMBER)
{
Rot = 180.0f;
}
else if (CharacterUpDirection.Dot(FVector::RightVector) > UE_KINDA_SMALL_NUMBER)
{
Rot = 90.0f;
}
else if (CharacterUpDirection.Dot(FVector::LeftVector) > UE_KINDA_SMALL_NUMBER)
{
Rot = 270.0f;
}
DesiredRotation.Roll = Rot;
DebugDesiredRotation = FString::Printf(TEXT("Desired Rotation after keeping it vertical: %s"), *DesiredRotation.ToString());
GEngine->AddOnScreenDebugMessage(-1, 0.0f, FColor::Cyan, DebugDesiredRotation);
}
else
{
DesiredRotation.Normalize();
}
// Accumulate a desired new rotation.
const float AngleTolerance = 1e-3f;
if (!CurrentRotation.Equals(DesiredRotation, AngleTolerance))
{
// PITCH
if (!FMath::IsNearlyEqual(CurrentRotation.Pitch, DesiredRotation.Pitch, AngleTolerance))
{
DesiredRotation.Pitch = FMath::FixedTurn(CurrentRotation.Pitch, DesiredRotation.Pitch, DeltaRot.Pitch);
}
// YAW
if (!FMath::IsNearlyEqual(CurrentRotation.Yaw, DesiredRotation.Yaw, AngleTolerance))
{
DesiredRotation.Yaw = FMath::FixedTurn(CurrentRotation.Yaw, DesiredRotation.Yaw, DeltaRot.Yaw);
}
// Set the new rotation.
DesiredRotation.DiagnosticCheckNaN(TEXT("CharacterMovementComponent::PhysicsRotation(): DesiredRotation"));
MoveUpdatedComponent( FVector::ZeroVector, DesiredRotation, /*bSweep*/ false );
}
}
void UGSCharacterMovementComponent::PhysWalking(float deltaTime, int32 Iterations)
{
if (deltaTime < MIN_TICK_TIME)

View File

@ -28,6 +28,8 @@ public:
virtual void OnMovementModeChanged(EMovementMode PreviousMovementMode, uint8 PreviousCustomMode) override;
virtual void PhysicsRotation(float DeltaTime) override;
// walking
virtual void PhysWalking(float deltaTime, int32 Iterations) override;
@ -58,5 +60,6 @@ public:
private:
FVector CharacterUpDirection = FVector::UpVector;
UFUNCTION(BlueprintPure)
FORCEINLINE bool IsCharacterUpAlignedToWorldUp() const;
};