diff --git a/SwordNGun/Content/Characters/Protagonist/BP_NewProtag.uasset b/SwordNGun/Content/Characters/Protagonist/BP_NewProtag.uasset index fa96808..f50171a 100644 --- a/SwordNGun/Content/Characters/Protagonist/BP_NewProtag.uasset +++ b/SwordNGun/Content/Characters/Protagonist/BP_NewProtag.uasset @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bebc7a07883dfb1c5a19300b03ac0e0cfe6319dd7fa9adc8ffe6545776dd26da -size 184810 +oid sha256:9273c229169b5e443f8b740b5a90ba8f1dbfa3f6c6f8efd92351340495a85d71 +size 184558 diff --git a/SwordNGun/Source/SwordNGun/Private/Characters/SNGCharacterBase.cpp b/SwordNGun/Source/SwordNGun/Private/Characters/SNGCharacterBase.cpp index 7f5fe67..224dd45 100644 --- a/SwordNGun/Source/SwordNGun/Private/Characters/SNGCharacterBase.cpp +++ b/SwordNGun/Source/SwordNGun/Private/Characters/SNGCharacterBase.cpp @@ -69,6 +69,7 @@ ASNGCharacterBase::ASNGCharacterBase(const FObjectInitializer& ObjectInitializer UE_LOG(LogTemp, Warning, TEXT("SNGCharacterBase :: Could not get skeletal mesh. Did you forget to set it?")); } + InputThreshold = 0.1f; DefaultFOV = 90.0f; SprintFOV = 110.0f; @@ -206,28 +207,51 @@ void ASNGCharacterBase::Tick(float DeltaTime) if(CharacterMovementDebug) { float LateralSpeed = GetVelocity().Size2D(); + FVector VelocityDir = GetVelocity(); + VelocityDir.Normalize(); + FVector LateralVelocityDir = FVector(VelocityDir.X, VelocityDir.Y, 0.0f); + FVector StartPos(GetActorLocation().X, GetActorLocation().Y, GetActorLocation().Z - GetCapsuleComponent()->GetScaledCapsuleHalfHeight()); FVector ActorForward = UKismetMathLibrary::GetForwardVector(GetActorRotation()); + + // Draw arrow showing velocity DrawDebugDirectionalArrow(GetWorld(), - StartPos, StartPos + (ActorForward * ((LateralSpeed / GetCharacterMovement()->MaxWalkSpeed) * 100.0f)), - 10.0f, FColor::Blue, false, -1.0f, 0, 2.0f); + StartPos, StartPos + (VelocityDir * ((GetVelocity().Size() / GetCharacterMovement()->MaxWalkSpeed) * 100.0f)), + 10.0f, FColor::Yellow, false, -1.0f, 0, 2.0f); + // Draw arrow showing lateral velocity + StartPos.Z += 1; // avoid z-fighting + DrawDebugDirectionalArrow(GetWorld(), + StartPos, StartPos + (LateralVelocityDir * ((LateralSpeed / GetCharacterMovement()->MaxWalkSpeed) * 100.0f)), + 10.0f, FColor::Orange, false, -1.0f, 0, 2.0f); + + // draw arrow showing what direction the player is inputting (WASD or right thumbstick) in the world relative to the camera FVector CurrInputDirection = GetInputAsWorldDirection(); CurrInputDirection.Normalize(); + StartPos.Z += 1; // avoid z-fighting DrawDebugDirectionalArrow(GetWorld(), StartPos, StartPos + (CurrInputDirection * 100.0f), 10.0f, FColor::Purple, false, -1.0f, 0, 2.0f); + // Draw arrow showing where character is facing + StartPos.Z += 1; // avoid z-fighting + DrawDebugDirectionalArrow(GetWorld(), + StartPos, StartPos + (ActorForward * 100.0f), + 10.0f, FColor::Blue, false, -1.0f, 0, 2.0f); + FString DebugMsg = FString::Printf(TEXT("MaxWalkSpeed: %f"), GetCharacterMovement()->MaxWalkSpeed); GEngine->AddOnScreenDebugMessage(-1, 0.0f, FColor::Magenta, DebugMsg); - 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); + + bool InputThresholdIsMet = CurrInputDirection.Size2D() >= InputThreshold; + DebugMsg = FString::Printf(TEXT("InputThresholdIsMet: %hs"), InputThresholdIsMet ? "true" : "false"); + GEngine->AddOnScreenDebugMessage(-1, 0.0f, FColor::Magenta, DebugMsg); if(ShowCharacterTrajectory) { @@ -260,6 +284,6 @@ void ASNGCharacterBase::SetupPlayerInputComponent(UInputComponent* PlayerInputCo // actions PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &ASNGCharacterBase::StartJump); - PlayerInputComponent->BindAction("Jump", IE_Released, this, &ASNGCharacterBase::StopJumping); + //PlayerInputComponent->BindAction("Jump", IE_Released, this, &ASNGCharacterBase::StopJumping); } diff --git a/SwordNGun/Source/SwordNGun/Private/Components/SNGCharacterMovementComponent.cpp b/SwordNGun/Source/SwordNGun/Private/Components/SNGCharacterMovementComponent.cpp index baeab38..44054ce 100644 --- a/SwordNGun/Source/SwordNGun/Private/Components/SNGCharacterMovementComponent.cpp +++ b/SwordNGun/Source/SwordNGun/Private/Components/SNGCharacterMovementComponent.cpp @@ -3,6 +3,7 @@ #include "Components/SNGCharacterMovementComponent.h" +#include "Characters/SNGCharacterBase.h" #include "GameFramework/Character.h" #include "Kismet/KismetMathLibrary.h" #include "PhysicsEngine/PhysicsSettings.h" @@ -33,6 +34,8 @@ USNGCharacterMovementComponent::USNGCharacterMovementComponent() // jump MaxJumpHeight = 250.0f; DesiredJumpDuration = 0.75f; + DefaultJumpLateralVelocity = DefaultMaxWalkSpeed; + LateralVelocityScaling = FVector2D(1.0f, 1.0f); ComputeGravityScaleAndJumpZVelocity(); // dash @@ -78,16 +81,16 @@ void USNGCharacterMovementComponent::RestoreMovementDefaults() void USNGCharacterMovementComponent::Dash() { - FLaunchParameters LaunchParams; - LaunchParams.bOverrideX = true; - LaunchParams.bOverrideY = true; - LaunchParams.bOverrideZ = true; - LaunchParams.bOverrideMovementMode = false; - LaunchParams.GroundFriction = DashGroundFriction; - LaunchParams.GravityScale = DashGravityScale; - LaunchParams.FloatTime = DashFloatTime; - LaunchParams.SlideTime = DashSlideTime; - + FLaunchParameters DashParams; + DashParams.bOverrideLateralVelocityClamping = true; + DashParams.bOverrideX = true; + DashParams.bOverrideY = true; + DashParams.bOverrideZ = true; + DashParams.bOverrideMovementMode = false; + DashParams.GroundFriction = DashGroundFriction; + DashParams.GravityScale = DashGravityScale; + DashParams.FloatTime = DashFloatTime; + DashParams.SlideTime = DashSlideTime; // sets gravity and friction targets which will start interpolating after float time and slide time elapse respectively TargetGravityScale = DefaultGravityScale; @@ -95,12 +98,12 @@ void USNGCharacterMovementComponent::Dash() GravityScaleInterpSpeed = DashGravityToDefaultSpeed; GroundFrictionInterpSpeed = DashGroundFrictionToDefaultSpeed; - FRotator CharacterRot = FRotator(0.0f, GetCharacterOwner()->GetActorRotation().Yaw, 0.0f); + FRotator CharacterRot = FRotator(0.0f, CharacterOwner->GetActorRotation().Yaw, 0.0f); FVector LaunchDir = FVector(UKismetMathLibrary::GetForwardVector(CharacterRot)); LaunchDir.Normalize(); - LaunchParams.Velocity = LaunchDir * DashVelocity; - LaunchCharacter(LaunchParams); + DashParams.Velocity = LaunchDir * DashVelocity; + LaunchCharacter(DashParams); } #if WITH_EDITOR @@ -135,8 +138,7 @@ void USNGCharacterMovementComponent::OnSprintTimer() void USNGCharacterMovementComponent::LaunchCharacter(const FLaunchParameters LaunchParams) { Velocity *= LaunchParams.VelocityScale; - - // + if(LaunchParams.bOverrideX) { Velocity.X = LaunchParams.Velocity.X; @@ -163,6 +165,14 @@ void USNGCharacterMovementComponent::LaunchCharacter(const FLaunchParameters Lau { Velocity.Z += LaunchParams.Velocity.Z; } + + if(!LaunchParams.bOverrideLateralVelocityClamping) + { + // clamp lateral velocity to max walk speed + FVector LateralVelocity = FVector(Velocity.X, Velocity.Y, 0.0f); + LateralVelocity = LateralVelocity.GetClampedToMaxSize(DefaultMaxWalkSpeed); + Velocity = FVector(LateralVelocity.X, LateralVelocity.Y, Velocity.Z); + } GroundFriction = LaunchParams.bUseDefaultGroundFriction ? DefaultGroundFriction : LaunchParams.GroundFriction; GravityScale = LaunchParams.bUseDefaultGravityScale ? DefaultGravityScale : LaunchParams.GravityScale; @@ -192,21 +202,41 @@ bool USNGCharacterMovementComponent::DoJump(bool bReplayingMoves) // Don't jump if we can't move up/down. if (!bConstrainToPlane || FMath::Abs(PlaneConstraintNormal.Z) != 1.f) { + ASNGCharacterBase* CharacterOwnerAsSNGChar = Cast(CharacterOwner); + if(CharacterOwnerAsSNGChar) + { + FLaunchParameters JumpParams; - FLaunchParameters JumpParams; - JumpParams.Velocity.Z = DefaultJumpZVelocity; - JumpParams.bOverrideX = false; - JumpParams.bOverrideY = false; - JumpParams.bOverrideZ = true; + FVector WorldInputDir = CharacterOwnerAsSNGChar->GetInputAsWorldDirection(); + if(WorldInputDir.Size2D() >= CharacterOwnerAsSNGChar->GetInputThreshold()) + { + FVector JumpLateralVelocity = WorldInputDir * DefaultJumpLateralVelocity; + JumpParams.Velocity.X = JumpLateralVelocity.X; + JumpParams.Velocity.Y = JumpLateralVelocity.Y; + } + + JumpParams.Velocity.Z = DefaultJumpZVelocity; + JumpParams.bOverrideLateralVelocityClamping = false; + JumpParams.bOverrideX = false; + JumpParams.bOverrideY = false; + JumpParams.bOverrideZ = true; - JumpParams.bUseDefaultGroundFriction = true; - JumpParams.bUseDefaultGravityScale = true; + JumpParams.VelocityScale = FVector(LateralVelocityScaling, 1.0f); + + JumpParams.bUseDefaultGroundFriction = true; + JumpParams.bUseDefaultGravityScale = true; - JumpParams.bOverrideMovementMode = true; - JumpParams.NewMovementMode = EMovementMode::MOVE_Falling; + JumpParams.bOverrideMovementMode = true; + JumpParams.NewMovementMode = EMovementMode::MOVE_Falling; - LaunchCharacter(JumpParams); - return true; + LaunchCharacter(JumpParams); + return true; + } + else + { + UE_LOG(LogTemp, Error, TEXT("SNGCharacterMovementComponent :: DoJump :: Could not cast CharacterOwner to ASNGCharacterBase")); + return false; + } } } diff --git a/SwordNGun/Source/SwordNGun/Public/Characters/SNGCharacterBase.h b/SwordNGun/Source/SwordNGun/Public/Characters/SNGCharacterBase.h index fac43d9..17ce8c5 100644 --- a/SwordNGun/Source/SwordNGun/Public/Characters/SNGCharacterBase.h +++ b/SwordNGun/Source/SwordNGun/Public/Characters/SNGCharacterBase.h @@ -18,6 +18,10 @@ public: // Sets default values for this character's properties ASNGCharacterBase(const FObjectInitializer& ObjectInitializer); + FVector GetInputAsWorldDirection(); + + FORCEINLINE float GetInputThreshold() { return InputThreshold; } + protected: UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Components") UCameraComponent* CameraComponent; @@ -28,6 +32,10 @@ protected: UPROPERTY(BlueprintReadOnly) FVector2D InputDirection; + /** Magnitude InputDirection needs to meet for the input to be considered "non-zero" */ + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Input") + float InputThreshold; + UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="Animations") UAnimMontage* JumpNeutralMontage; @@ -72,8 +80,6 @@ protected: // Called when the game starts or when spawned virtual void BeginPlay() override; - - FVector GetInputAsWorldDirection(); public: // Called every frame diff --git a/SwordNGun/Source/SwordNGun/Public/Components/SNGCharacterMovementComponent.h b/SwordNGun/Source/SwordNGun/Public/Components/SNGCharacterMovementComponent.h index 8f4a816..be23784 100644 --- a/SwordNGun/Source/SwordNGun/Public/Components/SNGCharacterMovementComponent.h +++ b/SwordNGun/Source/SwordNGun/Public/Components/SNGCharacterMovementComponent.h @@ -22,6 +22,10 @@ struct FLaunchParameters UPROPERTY(EditAnywhere, BlueprintReadWrite) FVector VelocityScale; + /** If true, lateral velocity will NOT be clamped to max walk speed after performing all other velocity update operations */ + UPROPERTY(EditAnywhere, BlueprintReadWrite) + bool bOverrideLateralVelocityClamping; + /** * Should the X component of character's velocity be overriden with Velocity parameter or added? * Default is false which means Velocity X component will be added to current character's velocity @@ -84,6 +88,7 @@ struct FLaunchParameters FLaunchParameters() : Velocity(FVector::ZeroVector) , VelocityScale(FVector::OneVector) + , bOverrideLateralVelocityClamping(false) , bOverrideX(false) , bOverrideY(false) , bOverrideZ(false) @@ -227,10 +232,6 @@ protected: UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="SNG Character Movement|Defaults|Air", meta=(ClampMin="0", UIMin="0")) float DefaultGravityScale; - /** How much to dampen lateral velocities at the start of a jump */ - UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="SNG Character Movement|Defaults|Air", meta=(ClampMin="0", UIMin="0")) - float LateralVelocityDampening; - /** Gravity Scale we want character to interpolate to. Interpolated based on GravityScaleInterpSpeed. */ UPROPERTY(BlueprintReadWrite) float TargetGravityScale; @@ -260,7 +261,7 @@ protected: UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="SNG Character Movement|Jump", meta=(ClampMin="0", UIMin="0")) float DesiredJumpDuration; - /** Force to continuously apply to character when they are holding the jump button */ + /** Z velocity set on the character when they are press the jump button */ UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="SNG Character Movement|Jump", meta=(ClampMin="0", UIMin="0")) float DefaultJumpZVelocity; @@ -272,6 +273,18 @@ protected: UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="SNG Character Movement|Jump", meta=(ClampMin="0", UIMin="0")) float MaxJumpTime; + /** + * Lateral velocity to set when the player initiates jump and is holding a direction. + * + * This value is multiplied by the world direction the player is inputting. + */ + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="SNG Character Movement|Jump", meta=(ClampMin="0", UIMin="0")) + float DefaultJumpLateralVelocity; + + /** How much to scale lateral velocity by when a jump is initiated */ + UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="SNG Character Movement|Jump", meta=(ClampMin="0", UIMin="0")) + FVector2D LateralVelocityScaling; + void ComputeGravityScaleAndJumpZVelocity(); virtual bool DoJump(bool bReplayingMoves) override;