feat: Smooth capsule while crouching. fix: slide

This commit is contained in:
NeonDmn 2025-06-01 19:22:52 +02:00
parent abcd8acc6f
commit 5e46f162d1
8 changed files with 86 additions and 59 deletions

Binary file not shown.

Binary file not shown.

View File

@ -9,7 +9,6 @@
#include "GameFramework/CharacterMovementComponent.h" #include "GameFramework/CharacterMovementComponent.h"
#include "Items/AmmoBoxBase.h" #include "Items/AmmoBoxBase.h"
#include "Items/HealthBoxBase.h" #include "Items/HealthBoxBase.h"
#include "Kismet/GameplayStatics.h"
#include "Player/InteractionComponent.h" #include "Player/InteractionComponent.h"
#include "Widget/WBP_PlayerUI.h" #include "Widget/WBP_PlayerUI.h"
@ -23,11 +22,6 @@ AExoPlayerCharacter::AExoPlayerCharacter()
CrouchedEyeHeight = 50.f; CrouchedEyeHeight = 50.f;
LowEyeHeightOffset = -20.f; LowEyeHeightOffset = -20.f;
CapsuleBottom = CreateDefaultSubobject<USceneComponent>(TEXT("CapsuleBottom"));
CapsuleBottom->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepRelativeTransform);
CapsuleBottom->SetRelativeLocation(FVector(0, 0, -GetCapsuleComponent()->GetScaledCapsuleHalfHeight()));
// Create camera component // Create camera component
CameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("CameraComponent")); CameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("CameraComponent"));
CameraComponent->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepRelativeTransform); CameraComponent->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepRelativeTransform);
@ -57,10 +51,18 @@ void AExoPlayerCharacter::BeginPlay()
// Set correct starting camera height // Set correct starting camera height
SetTargetEyeHeight(StandingEyeHeight); SetTargetEyeHeight(StandingEyeHeight);
CameraComponent->SetRelativeLocation(FVector(0.0f, 0.0f, FromFeet(TargetEyeHeight))); CameraComponent->SetRelativeLocation(FVector(0.0f, 0.0f, TargetEyeHeight + GetFootOffset()));
GetCapsuleComponent()->OnComponentBeginOverlap.AddDynamic(this, &AExoPlayerCharacter::OnActorBeginOverlap); GetCapsuleComponent()->OnComponentBeginOverlap.AddDynamic(this, &AExoPlayerCharacter::OnActorBeginOverlap);
// Setup crouch timeline
FOnTimelineFloat ProgressUpdate;
ProgressUpdate.BindUFunction(this, FName("CrouchingUpdate"));
FOnTimelineEvent FinishedEvent;
FinishedEvent.BindUFunction(this, FName("CrouchingFinished"));
CrouchTimeline.AddInterpFloat(CapsuleResizeCurve, ProgressUpdate);
CrouchTimeline.SetTimelineFinishedFunc(FinishedEvent);
PlayerHud = CreateWidget<UWBP_PlayerUI>(GetWorld(),PlayerHudClass); PlayerHud = CreateWidget<UWBP_PlayerUI>(GetWorld(),PlayerHudClass);
if (PlayerHud) if (PlayerHud)
@ -83,6 +85,8 @@ void AExoPlayerCharacter::Tick(float DeltaTime)
{ {
Super::Tick(DeltaTime); Super::Tick(DeltaTime);
CrouchTimeline.TickTimeline(2*DeltaTime);
UpdateCameraHeight(DeltaTime); UpdateCameraHeight(DeltaTime);
ApplyCameraOffsets(DeltaTime); ApplyCameraOffsets(DeltaTime);
} }
@ -92,6 +96,25 @@ float AExoPlayerCharacter::GetFootOffset()
return -GetCapsuleComponent()->GetScaledCapsuleHalfHeight(); return -GetCapsuleComponent()->GetScaledCapsuleHalfHeight();
} }
void AExoPlayerCharacter::CrouchingUpdate(float Alpha)
{
float CurrentCamHeight = GetCurrentEyeHeight();
float NewHalfHeight = FMath::Lerp(
StandingHalfHeight, GetCharacterMovement()->CrouchedHalfHeight, Alpha);
GetCapsuleComponent()->SetCapsuleHalfHeight(NewHalfHeight);
CameraComponent->SetRelativeLocation(
FVector(0, 0, GetFootOffset()) +
FVector(0, 0, CurrentCamHeight));
UE_LOG(LogTemp, Display, TEXT("Crouching Update"));
}
void AExoPlayerCharacter::CrouchingFinished()
{
}
void AExoPlayerCharacter::UpdateCameraHeight(float DeltaTime) void AExoPlayerCharacter::UpdateCameraHeight(float DeltaTime)
{ {
if (FMath::IsNearlyEqual(GetCurrentEyeHeight(), TargetEyeHeight, 0.01f)) if (FMath::IsNearlyEqual(GetCurrentEyeHeight(), TargetEyeHeight, 0.01f))
@ -176,24 +199,27 @@ void AExoPlayerCharacter::CrouchCustom()
SetTargetEyeHeight(CrouchedEyeHeight); SetTargetEyeHeight(CrouchedEyeHeight);
GetCharacterMovement()->MaxWalkSpeed = CrouchSpeed; GetCharacterMovement()->MaxWalkSpeed = CrouchSpeed;
bIsCrouched = true; bIsCrouched = true;
CrouchTimeline.Play();
float CurrentCamHeight = GetCurrentEyeHeight(); //float CurrentCamHeight = GetCurrentEyeHeight();
GetCapsuleComponent()->SetCapsuleHalfHeight(GetCharacterMovement()->CrouchedHalfHeight); //GetCapsuleComponent()->SetCapsuleHalfHeight(GetCharacterMovement()->CrouchedHalfHeight);
CameraComponent->SetRelativeLocation( // CameraComponent->SetRelativeLocation(
FVector(0, 0, GetFootOffset()) + // FVector(0, 0, GetFootOffset()) +
FVector(0, 0, CurrentCamHeight)); // FVector(0, 0, CurrentCamHeight));
} }
void AExoPlayerCharacter::TryUnCrouchCustom() void AExoPlayerCharacter::TryUnCrouchCustom()
{ {
SetTargetEyeHeight(StandingEyeHeight); SetTargetEyeHeight(StandingEyeHeight);
GetCharacterMovement()->MaxWalkSpeed = WalkSpeed; GetCharacterMovement()->MaxWalkSpeed = WalkSpeed;
bIsCrouched = false;
CrouchTimeline.Reverse();
float CurrentCamHeight = GetCurrentEyeHeight(); //float CurrentCamHeight = GetCurrentEyeHeight();
GetCapsuleComponent()->SetCapsuleHalfHeight(StandingHalfHeight); //GetCapsuleComponent()->SetCapsuleHalfHeight(StandingHalfHeight);
CameraComponent->SetRelativeLocation( //CameraComponent->SetRelativeLocation(
FVector(0, 0, GetFootOffset()) + // FVector(0, 0, GetFootOffset()) +
FVector(0, 0, CurrentCamHeight)); // FVector(0, 0, CurrentCamHeight));
} }
void AExoPlayerCharacter::AddHealthPoints(float addValue) void AExoPlayerCharacter::AddHealthPoints(float addValue)
@ -207,26 +233,6 @@ void AExoPlayerCharacter::AddHealthPoints(float addValue)
PlayerHud->SetHp(CurrentHealth,MaxHealth); PlayerHud->SetHp(CurrentHealth,MaxHealth);
} }
float AExoPlayerCharacter::ToFeet(float value)
{
return value + GetCapsuleComponent()->GetScaledCapsuleHalfHeight();
}
float AExoPlayerCharacter::FromFeet(float value)
{
return value - GetCapsuleComponent()->GetScaledCapsuleHalfHeight();
}
/*float AExoPlayerCharacter::GetCurrentEyeHeightBase(const bool bCapsuleRelative)
{
if (bIsCrouched)
{
return GetCrouchingEyeHeight(bCapsuleRelative);
}
return GetStandingEyeHeight(bCapsuleRelative);
}*/
float AExoPlayerCharacter::GetStandingEyeHeight(const bool bCapsuleRelative) const float AExoPlayerCharacter::GetStandingEyeHeight(const bool bCapsuleRelative) const
{ {
return bCapsuleRelative ? StandingEyeHeight - GetCapsuleComponent()->GetScaledCapsuleHalfHeight() return bCapsuleRelative ? StandingEyeHeight - GetCapsuleComponent()->GetScaledCapsuleHalfHeight()
@ -276,7 +282,7 @@ void AExoPlayerCharacter::SetTargetEyeHeight(float NewEyeHeight, const bool bCap
); );
} }
float AExoPlayerCharacter::GetCurrentEyeHeight(const bool bCapsuleRelative) float AExoPlayerCharacter::GetCurrentEyeHeight(const bool bCapsuleRelative) const
{ {
float ReturnValue = CameraComponent->GetRelativeLocation().Z; float ReturnValue = CameraComponent->GetRelativeLocation().Z;
if (!bCapsuleRelative) if (!bCapsuleRelative)

View File

@ -118,6 +118,8 @@ void AExoPlayerController::Interact()
void AExoPlayerController::PlayerJump() void AExoPlayerController::PlayerJump()
{ {
if (PlayerCharacter->IsCrouching()) return;
PlayerCharacter->Jump(); PlayerCharacter->Jump();
} }
@ -151,13 +153,13 @@ void AExoPlayerController::ResetDodge()
void AExoPlayerController::PlayerStartCrouch() void AExoPlayerController::PlayerStartCrouch()
{ {
if (bIsSprinting) if (bIsSprinting && !bWasSliding)
{ {
PlayerCharacter->GetCharacterMovement()->MaxWalkSpeedCrouched = PlayerCharacter->SlideSpeed; StartSlide();
PlayerCharacter->SetTargetEyeHeight(PlayerCharacter->LowEyeHeightOffset); return;
GetWorldTimerManager().SetTimer(SlideCooldownTimer, this, &AExoPlayerController::ResetSlide, PlayerCharacter->SlideCooldown, false);
} }
bWasSliding = false;
PlayerCharacter->CrouchCustom(); PlayerCharacter->CrouchCustom();
// Start checking for cover // Start checking for cover
@ -180,10 +182,21 @@ void AExoPlayerController::PlayerStopCrouch()
PlayerCharacter->bIsInCover = false; PlayerCharacter->bIsInCover = false;
} }
void AExoPlayerController::StartSlide()
{
bIsSliding = true;
PlayerCharacter->GetCharacterMovement()->MaxWalkSpeed = PlayerCharacter->SlideSpeed;
PlayerCharacter->SetTargetEyeHeight(PlayerCharacter->LowEyeHeightOffset);
GetWorldTimerManager().SetTimer(SlideCooldownTimer, this, &AExoPlayerController::ResetSlide, PlayerCharacter->SlideCooldown, false);
}
void AExoPlayerController::ResetSlide() void AExoPlayerController::ResetSlide()
{ {
PlayerCharacter->GetCharacterMovement()->MaxWalkSpeedCrouched = PlayerCharacter->CrouchSpeed; bIsSliding = false;
PlayerCharacter->SetTargetEyeHeight(PlayerCharacter->CrouchedEyeHeight); bWasSliding = true;
PlayerStartCrouch();
//PlayerCharacter->GetCharacterMovement()->MaxWalkSpeed = PlayerCharacter->CrouchSpeed;
//PlayerCharacter->SetTargetEyeHeight(PlayerCharacter->CrouchedEyeHeight);
} }
void AExoPlayerController::PlayerStartSprint() void AExoPlayerController::PlayerStartSprint()

View File

@ -5,6 +5,7 @@
#include "CoreMinimal.h" #include "CoreMinimal.h"
#include "Camera/CameraComponent.h" #include "Camera/CameraComponent.h"
#include "Characters/ExoCharacterBase.h" #include "Characters/ExoCharacterBase.h"
#include "Components/TimelineComponent.h"
#include "ExoPlayerCharacter.generated.h" #include "ExoPlayerCharacter.generated.h"
class UInteractionComponent; class UInteractionComponent;
@ -80,6 +81,9 @@ public:
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Camera") UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Camera")
float LowEyeHeightOffset; float LowEyeHeightOffset;
UPROPERTY(EditAnywhere)
TObjectPtr<UCurveFloat> CapsuleResizeCurve;
/// U FUNCTIONS /// /// U FUNCTIONS ///
UFUNCTION() UFUNCTION()
@ -102,16 +106,6 @@ public:
UFUNCTION() UFUNCTION()
void AddHealthPoints(float addValue); void AddHealthPoints(float addValue);
/** Przekształca wartość relatywną do pozycji środka kapsuły gracza
* na wartość relatywną do pozycji stóp gracza */
UFUNCTION(BlueprintPure)
float ToFeet(float Value);
/** Przekształca wartość relatywną do pozycji stóp kapsuły gracza
* na wartość relatywną do pozycji kapsuły gracza */
UFUNCTION(BlueprintPure)
float FromFeet(float Value);
UFUNCTION(BlueprintCallable, Category="Camera") UFUNCTION(BlueprintCallable, Category="Camera")
void SetEyePositionOffsetTarget(FVector LocationOffset); void SetEyePositionOffsetTarget(FVector LocationOffset);
@ -125,10 +119,7 @@ public:
void SetTargetEyeHeight(float NewEyeHeight, const bool bCapsuleRelative = false); void SetTargetEyeHeight(float NewEyeHeight, const bool bCapsuleRelative = false);
UFUNCTION(BlueprintCallable, Category="Camera") UFUNCTION(BlueprintCallable, Category="Camera")
float GetCurrentEyeHeight(const bool bCapsuleRelative = false); float GetCurrentEyeHeight(const bool bCapsuleRelative = false) const;
//UFUNCTION(BlueprintCallable, Category="Camera")
//float GetCurrentEyeHeightBase(const bool bCapsuleRelative = false);
UFUNCTION(BlueprintPure, Category="Camera") UFUNCTION(BlueprintPure, Category="Camera")
float GetStandingEyeHeight(const bool bCapsuleRelative = false) const; float GetStandingEyeHeight(const bool bCapsuleRelative = false) const;
@ -170,6 +161,14 @@ private:
float TargetEyeHeight; float TargetEyeHeight;
float EyeHeight; float EyeHeight;
FTimeline CrouchTimeline;
UFUNCTION()
void CrouchingUpdate(float Alpha);
UFUNCTION()
void CrouchingFinished();
void UpdateCameraHeight(float DeltaTime); void UpdateCameraHeight(float DeltaTime);
void ApplyCameraOffsets(float DeltaTime); void ApplyCameraOffsets(float DeltaTime);
}; };

View File

@ -56,6 +56,9 @@ protected:
UFUNCTION(BlueprintCallable, Category = "Input") UFUNCTION(BlueprintCallable, Category = "Input")
void PlayerStopCrouch(); // LCtrl\C\X void PlayerStopCrouch(); // LCtrl\C\X
UFUNCTION(BlueprintCallable, Category = "Movement")
void StartSlide();
UFUNCTION(BlueprintCallable, Category = "Input") UFUNCTION(BlueprintCallable, Category = "Input")
void ResetSlide(); void ResetSlide();
@ -142,6 +145,9 @@ protected:
UPROPERTY(EditAnywhere, Category = "Movement properties") UPROPERTY(EditAnywhere, Category = "Movement properties")
bool bIsSprinting = false; bool bIsSprinting = false;
UPROPERTY(EditAnywhere, Category = "Movement properties")
bool bIsSliding = false;
UPROPERTY(EditAnywhere, Category = "Input") UPROPERTY(EditAnywhere, Category = "Input")
TObjectPtr<UInputAction> ShootAction; TObjectPtr<UInputAction> ShootAction;
@ -230,4 +236,7 @@ private:
FTimerHandle CoverCheckTimer; FTimerHandle CoverCheckTimer;
float MaxCoverAimHeight; float MaxCoverAimHeight;
float CoverAimHeightOffset; float CoverAimHeightOffset;
// temporary
bool bWasSliding = false;
}; };