Sprinting and movement debug visuals

This commit is contained in:
Kevin Poretti 2022-03-13 22:07:13 -04:00
parent 0a8720f706
commit 292989f26b
11 changed files with 192 additions and 42 deletions

Binary file not shown.

BIN
SwordNGun/Content/Maps/MovementTest.umap (Stored with Git LFS)

Binary file not shown.

View File

@ -11,12 +11,33 @@
#include "Kismet/KismetMathLibrary.h" #include "Kismet/KismetMathLibrary.h"
static int32 ShowCharacterMovementDebug = 0; static int32 CharacterMovementDebug = 0;
FAutoConsoleVariableRef CVARShowCharacterMovementDebug(TEXT("SNG.ShowCharacterMovementDebug"), FAutoConsoleVariableRef CVARCharacterMovementDebug(TEXT("SNG.CharacterMovementDebug.Show"),
ShowCharacterMovementDebug, CharacterMovementDebug,
TEXT("Print movement information for character"), TEXT("Print movement information for character"),
ECVF_Cheat); ECVF_Cheat);
static int32 ShowCharacterTrajectory = 0;
FAutoConsoleVariableRef CVARShowCharacterTrajectory(TEXT("SNG.CharacterMovementDebug.Trajectory.Show"),
ShowCharacterTrajectory,
TEXT("Render character trajectory"),
ECVF_Cheat);
static float TrajectoryPeriod = 0.05f;
FAutoConsoleVariableRef CVARTrajectoryPeriod(TEXT("SNG.CharacterMovementDebug.Trajectory.Period"),
TrajectoryPeriod,
TEXT("How often should trajectory lines be drawn"),
ECVF_Cheat);
static float TrajectoryLineLifetime = 10.0f;
FAutoConsoleVariableRef CVARTrajectoryLineLifetime(TEXT("SNG.CharacterMovementDebug.Trajectory.Lifetime"),
TrajectoryLineLifetime,
TEXT("How long should a trajectory line segment be visible"),
ECVF_Cheat);
static float LastSavedPosTime = 0.0f;
static FVector LastSavedPos = FVector::ZeroVector;
// Sets default values // Sets default values
ASNGCharacterBase::ASNGCharacterBase(const FObjectInitializer& ObjectInitializer) ASNGCharacterBase::ASNGCharacterBase(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer.SetDefaultSubobjectClass<USNGCharacterMovementComponent>(ACharacter::CharacterMovementComponentName)) : Super(ObjectInitializer.SetDefaultSubobjectClass<USNGCharacterMovementComponent>(ACharacter::CharacterMovementComponentName))
@ -48,6 +69,11 @@ ASNGCharacterBase::ASNGCharacterBase(const FObjectInitializer& ObjectInitializer
{ {
UE_LOG(LogTemp, Warning, TEXT("SNGCharacterBase :: Could not get skeletal mesh. Did you forget to set it?")); UE_LOG(LogTemp, Warning, TEXT("SNGCharacterBase :: Could not get skeletal mesh. Did you forget to set it?"));
} }
DefaultFOV = 90.0f;
SprintFOV = 110.0f;
SprintFOVInterpSpeed = 2.0f;
} }
void ASNGCharacterBase::MoveForward(float Value) void ASNGCharacterBase::MoveForward(float Value)
@ -162,19 +188,48 @@ void ASNGCharacterBase::Tick(float DeltaTime)
{ {
Super::Tick(DeltaTime); Super::Tick(DeltaTime);
if(ShowCharacterMovementDebug) USNGCharacterMovementComponent* CharMovement = Cast<USNGCharacterMovementComponent>(GetCharacterMovement());
check(CharMovement);
// interpolate to appropriate field of view depending on whether player sprinting or not
float TargetFOV = CharMovement->GetIsSprinting() ? SprintFOV : DefaultFOV;
float NewFOV = FMath::FInterpTo(CameraComponent->FieldOfView, TargetFOV, DeltaTime, SprintFOVInterpSpeed);
CameraComponent->SetFieldOfView(NewFOV);
// Debug
if(CharacterMovementDebug)
{ {
FVector StartPos = GetActorLocation() - GetCapsuleComponent()->GetScaledCapsuleHalfHeight(); FVector StartPos(GetActorLocation().X,
GetActorLocation().Y,
GetActorLocation().Z - GetCapsuleComponent()->GetScaledCapsuleHalfHeight());
FVector ActorForward = UKismetMathLibrary::GetForwardVector(GetActorRotation()); FVector ActorForward = UKismetMathLibrary::GetForwardVector(GetActorRotation());
DrawDebugDirectionalArrow(GetWorld(), StartPos, StartPos + (ActorForward * 100.0f), DrawDebugDirectionalArrow(GetWorld(), StartPos, StartPos + (ActorForward * 100.0f),
10.0f, FColor::Cyan, false, -1.0f, 0, 2.0f); 10.0f, FColor::Blue, false, -1.0f, 0, 2.0f);
FVector CurrInputDirection = GetInputAsWorldDirection(); FVector CurrInputDirection = GetInputAsWorldDirection();
CurrInputDirection.Normalize(); CurrInputDirection.Normalize();
DrawDebugDirectionalArrow(GetWorld(), StartPos, StartPos + (CurrInputDirection * 100.0f), DrawDebugDirectionalArrow(GetWorld(), StartPos, StartPos + (CurrInputDirection * 100.0f),
10.0f, FColor::Magenta, false, -1.0f, 0, 2.0f); 10.0f, FColor::Purple, false, -1.0f, 0, 2.0f);
FString DebugMsg = FString::Printf(TEXT("MaxWalkSpeed: %f"), GetCharacterMovement()->MaxWalkSpeed);
GEngine->AddOnScreenDebugMessage(-1, 0.0f, FColor::Magenta, DebugMsg);
float LateralSpeed = GetVelocity().Size2D();
DebugMsg = FString::Printf(TEXT("LateralSpeed: %f"), LateralSpeed);
GEngine->AddOnScreenDebugMessage(-1, 0.0f, FColor::Magenta, DebugMsg);
DebugMsg = FString::Printf(TEXT("RotationRate: %s"), *GetCharacterMovement()->RotationRate.ToString());
GEngine->AddOnScreenDebugMessage(-1, 0.0f, FColor::Magenta, DebugMsg);
if(ShowCharacterTrajectory)
{
if(GetWorld()->TimeSeconds - LastSavedPosTime >= TrajectoryPeriod)
{
DrawDebugLine(GetWorld(), LastSavedPos, StartPos, FColor::Red, false, TrajectoryLineLifetime, 0, 2.0f);
LastSavedPos = StartPos;
LastSavedPosTime = GetWorld()->TimeSeconds;
}
}
} }
} }
// Called to bind functionality to input // Called to bind functionality to input

View File

@ -3,16 +3,29 @@
#include "Components/SNGCharacterMovementComponent.h" #include "Components/SNGCharacterMovementComponent.h"
#include "Kismet/KismetMathLibrary.h"
USNGCharacterMovementComponent::USNGCharacterMovementComponent() USNGCharacterMovementComponent::USNGCharacterMovementComponent()
{ {
// Set defaults dealing with grounded movement // Defaults
DefaultGroundFriction = 8.0f; DefaultGroundFriction = 8.0f;
DefaultGravityScale = 1.0f; DefaultGravityScale = 1.0f;
DefaultMaxWalkSpeed = 475.0f; DefaultMaxWalkSpeed = 600.0f;
FiringMaxWalkSpeed = 300.0f; DefaultRotationRate = FRotator(0.0f, 360.0f, 0.0f);
ReloadingMaxWalkSpeed = 300.0f;
SprintingMaxWalkSpeed = 600.0f; // sprint
SprintingMaxWalkSpeed = 800.0f;
SprintLateralSpeedThreshold = 300.0f;
SprintingRotationRate = FRotator(0.0f, 180.0f, 0.0f);
TimeToInitiateSprint = 4.0f;
WalkToSprintInterpSpeed = 1.0f;
// firing
FiringMaxWalkSpeed = 300.0f;
// reloading
ReloadingMaxWalkSpeed = 300.0f;
// Set defaults dealing with jumping and being airborne // Set defaults dealing with jumping and being airborne
DefaultJumpForce = 1000.0f; DefaultJumpForce = 1000.0f;
DefaultAirFriction = 150.0f; DefaultAirFriction = 150.0f;
@ -35,12 +48,18 @@ void USNGCharacterMovementComponent::RestoreMovementDefaults()
{ {
GroundFriction = DefaultGroundFriction; GroundFriction = DefaultGroundFriction;
GravityScale = DefaultGravityScale; GravityScale = DefaultGravityScale;
RotationRate = DefaultRotationRate;
MaxWalkSpeed = DefaultMaxWalkSpeed; MaxWalkSpeed = DefaultMaxWalkSpeed;
BrakingDecelerationFalling = DefaultAirFriction; BrakingDecelerationFalling = DefaultAirFriction;
AirControl = DefaultAirControl; AirControl = DefaultAirControl;
JumpZVelocity = DefaultJumpForce; JumpZVelocity = DefaultJumpForce;
} }
void USNGCharacterMovementComponent::OnSprintTimer()
{
bIsSprinting = true;
}
void USNGCharacterMovementComponent::StartJump() void USNGCharacterMovementComponent::StartJump()
{ {
/* /*
@ -75,5 +94,31 @@ void USNGCharacterMovementComponent::TickComponent(float DeltaTime, ELevelTick T
{ {
Super::TickComponent(DeltaTime, Tick, ThisTickFunction); Super::TickComponent(DeltaTime, Tick, ThisTickFunction);
float LateralSpeed = Velocity.Size2D();
if(LateralSpeed >= SprintLateralSpeedThreshold && !GetWorld()->GetTimerManager().IsTimerActive(TimerHandle_SprintTimer) )
{
GetWorld()->GetTimerManager().SetTimer(TimerHandle_SprintTimer,
this, &USNGCharacterMovementComponent::OnSprintTimer,
TimeToInitiateSprint, false);
}
if(LateralSpeed < SprintLateralSpeedThreshold && GetWorld()->GetTimerManager().IsTimerActive(TimerHandle_SprintTimer))
{
GetWorld()->GetTimerManager().ClearTimer(TimerHandle_SprintTimer);
bIsSprinting = false;
}
// set walk speed and rotation rate depending on whether player is sprinting or not
float TargetMaxWalkSpeed = bIsSprinting ? SprintingMaxWalkSpeed : DefaultMaxWalkSpeed;
float NewMaxWalkSpeed = FMath::FInterpTo(MaxWalkSpeed, TargetMaxWalkSpeed, DeltaTime, WalkToSprintInterpSpeed);
MaxWalkSpeed = NewMaxWalkSpeed;
// NOTE(kevin): since default rotate rate is 360 RInterpTo will go from 0 to 180 instead of 360 to 180
// need to think of a way to prevent this
// might just need to do my own interp manually
/*
FRotator TargetRotationRate = bIsSprinting ? SprintingRotationRate : DefaultRotationRate;
FRotator NewRotationRate = FMath::RInterpTo(RotationRate, TargetRotationRate, DeltaTime, WalkToSprintInterpSpeed);
RotationRate = NewRotationRate;
*/
} }

View File

@ -42,6 +42,18 @@ protected:
UPROPERTY(BlueprintReadWrite) UPROPERTY(BlueprintReadWrite)
bool CanMovementCancelMontage; bool CanMovementCancelMontage;
/** Field of the view the camera starts with */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Field Of View", meta=(ClampMin="30", UIMin="30"))
float DefaultFOV;
/** Field of the view when the player starts sprinting */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Field Of View", meta=(ClampMin="30", UIMin="30"))
float SprintFOV;
/** */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Field Of View", meta=(ClampMin="0", UIMin="0"))
float SprintFOVInterpSpeed;
void MoveForward(float Value); void MoveForward(float Value);

View File

@ -27,45 +27,83 @@ public:
UFUNCTION(BlueprintCallable) UFUNCTION(BlueprintCallable)
void RestoreMovementDefaults(); void RestoreMovementDefaults();
/**
* Gets bool whether the character is currently in the sprinting state
*/
UFUNCTION(BlueprintCallable)
FORCEINLINE bool GetIsSprinting() { return bIsSprinting; }
protected: protected:
// default ground
/** Default friction when not performing any special actions and on the ground */ /** Default friction when not performing any special actions and on the ground */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Character Movement: SNG Ground Defaults", meta=(ClampMin="0", UIMin="0")) UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="SNG Character Movement.Ground.Defaults", meta=(ClampMin="0", UIMin="0"))
float DefaultGroundFriction; float DefaultGroundFriction;
/** Default ground walk speed when not performing any special actions */ /** Default ground walk speed when not performing any special actions */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Character Movement: SNG Ground Defaults", meta=(ClampMin="0", UIMin="0")) UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="SNG Character Movement.Ground.Defaults", meta=(ClampMin="0", UIMin="0"))
float DefaultMaxWalkSpeed; float DefaultMaxWalkSpeed;
/** Ground walk speed when firing a ranged weapon */ /** Default ground walk speed when not performing any special actions */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Character Movement: SNG Ground Defaults", meta=(ClampMin="0", UIMin="0")) UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="SNG Character Movement.Ground.Defaults", meta=(ClampMin="0", UIMin="0"))
float FiringMaxWalkSpeed; FRotator DefaultRotationRate;
/** Ground walk speed when reloading a ranged weapon */ // sprinting
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Character Movement: SNG Ground Defaults", meta=(ClampMin="0", UIMin="0"))
float ReloadingMaxWalkSpeed;
/** Ground walk speed when sprinting */ /** Ground walk speed when sprinting */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Character Movement: SNG Ground Defaults", meta=(ClampMin="0", UIMin="0")) UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="SNG Character Movement.Ground.Sprint", meta=(ClampMin="0", UIMin="0"))
float SprintingMaxWalkSpeed; float SprintingMaxWalkSpeed;
/** Lateral speed the player needs to maintain to stay in the sprinting state */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="SNG Character Movement.Ground.Sprint", meta=(ClampMin="0", UIMin="0"))
float SprintLateralSpeedThreshold;
/** Default ground walk speed when not performing any special actions */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="SNG Character Movement.Ground.Sprint", meta=(ClampMin="0", UIMin="0"))
FRotator SprintingRotationRate;
/** How long after applying movement input should the character start sprinting? */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="SNG Character Movement.Ground.Sprint", meta=(ClampMin="0", UIMin="0"))
float TimeToInitiateSprint;
/** The speed in which the max walk speed to interpolated to the max sprint speed when a sprint has been initiated */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="SNG Character Movement.Ground.Sprint", meta=(ClampMin="0", UIMin="0"))
float WalkToSprintInterpSpeed;
FTimerHandle TimerHandle_SprintTimer;
UPROPERTY(BlueprintReadOnly)
bool bIsSprinting;
void OnSprintTimer();
// firing
/** Ground walk speed when firing a ranged weapon */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="SNG Character Movement.Firing", meta=(ClampMin="0", UIMin="0"))
float FiringMaxWalkSpeed;
// reloading
/** Ground walk speed when reloading a ranged weapon */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="SNG Character Movement.Reloading", meta=(ClampMin="0", UIMin="0"))
float ReloadingMaxWalkSpeed;
// airborne
/** Gravity scale when not performing any special actions */ /** Gravity scale when not performing any special actions */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Character Movement: SNG Air Defaults", meta=(ClampMin="0", UIMin="0")) UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="SNG Character Movement.Air.Defaults", meta=(ClampMin="0", UIMin="0"))
float DefaultGravityScale; float DefaultGravityScale;
/** Force to continuously apply to character when they are holding the jump button */ /** Force to continuously apply to character when they are holding the jump button */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Character Movement: SNG Air Defaults", meta=(ClampMin="0", UIMin="0")) UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="SNG Character Movement.Air.Defaults", meta=(ClampMin="0", UIMin="0"))
float DefaultJumpForce; float DefaultJumpForce;
/** Minimum height a character must reach before jump force is no longer applied even if the jump input is not being held */ /** Minimum height a character must reach before jump force is no longer applied even if the jump input is not being held */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Character Movement: SNG Air Defaults", meta=(ClampMin="0", UIMin="0")) UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="SNG Character Movement.Air.Defaults", meta=(ClampMin="0", UIMin="0"))
float MinJumpHeight; float MinJumpHeight;
/** Max time the jump button can be held to give character upward velocity */ /** Max time the jump button can be held to give character upward velocity */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Character Movement: SNG Air Defaults", meta=(ClampMin="0", UIMin="0")) UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="SNG Character Movement.Air.Defaults", meta=(ClampMin="0", UIMin="0"))
float MaxJumpTime; float MaxJumpTime;
/** How much to dampen lateral velocities at the start of a jump */ /** How much to dampen lateral velocities at the start of a jump */
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Character Movement: SNG Air Defaults", meta=(ClampMin="0", UIMin="0")) UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="SNG Character Movement.Air.Defaults", meta=(ClampMin="0", UIMin="0"))
float LateralVelocityDampening; float LateralVelocityDampening;
/** /**