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 "Items/AmmoBoxBase.h"
#include "Items/HealthBoxBase.h"
#include "Kismet/GameplayStatics.h"
#include "Player/InteractionComponent.h"
#include "Widget/WBP_PlayerUI.h"
@ -23,11 +22,6 @@ AExoPlayerCharacter::AExoPlayerCharacter()
CrouchedEyeHeight = 50.f;
LowEyeHeightOffset = -20.f;
CapsuleBottom = CreateDefaultSubobject<USceneComponent>(TEXT("CapsuleBottom"));
CapsuleBottom->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepRelativeTransform);
CapsuleBottom->SetRelativeLocation(FVector(0, 0, -GetCapsuleComponent()->GetScaledCapsuleHalfHeight()));
// Create camera component
CameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("CameraComponent"));
CameraComponent->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepRelativeTransform);
@ -57,11 +51,19 @@ void AExoPlayerCharacter::BeginPlay()
// Set correct starting camera height
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);
// 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);
if (PlayerHud)
{
@ -82,6 +84,8 @@ void AExoPlayerCharacter::BeginPlay()
void AExoPlayerCharacter::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
CrouchTimeline.TickTimeline(2*DeltaTime);
UpdateCameraHeight(DeltaTime);
ApplyCameraOffsets(DeltaTime);
@ -92,6 +96,25 @@ float AExoPlayerCharacter::GetFootOffset()
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)
{
if (FMath::IsNearlyEqual(GetCurrentEyeHeight(), TargetEyeHeight, 0.01f))
@ -176,24 +199,27 @@ void AExoPlayerCharacter::CrouchCustom()
SetTargetEyeHeight(CrouchedEyeHeight);
GetCharacterMovement()->MaxWalkSpeed = CrouchSpeed;
bIsCrouched = true;
CrouchTimeline.Play();
float CurrentCamHeight = GetCurrentEyeHeight();
GetCapsuleComponent()->SetCapsuleHalfHeight(GetCharacterMovement()->CrouchedHalfHeight);
CameraComponent->SetRelativeLocation(
FVector(0, 0, GetFootOffset()) +
FVector(0, 0, CurrentCamHeight));
//float CurrentCamHeight = GetCurrentEyeHeight();
//GetCapsuleComponent()->SetCapsuleHalfHeight(GetCharacterMovement()->CrouchedHalfHeight);
// CameraComponent->SetRelativeLocation(
// FVector(0, 0, GetFootOffset()) +
// FVector(0, 0, CurrentCamHeight));
}
void AExoPlayerCharacter::TryUnCrouchCustom()
{
SetTargetEyeHeight(StandingEyeHeight);
GetCharacterMovement()->MaxWalkSpeed = WalkSpeed;
bIsCrouched = false;
CrouchTimeline.Reverse();
float CurrentCamHeight = GetCurrentEyeHeight();
GetCapsuleComponent()->SetCapsuleHalfHeight(StandingHalfHeight);
CameraComponent->SetRelativeLocation(
FVector(0, 0, GetFootOffset()) +
FVector(0, 0, CurrentCamHeight));
//float CurrentCamHeight = GetCurrentEyeHeight();
//GetCapsuleComponent()->SetCapsuleHalfHeight(StandingHalfHeight);
//CameraComponent->SetRelativeLocation(
// FVector(0, 0, GetFootOffset()) +
// FVector(0, 0, CurrentCamHeight));
}
void AExoPlayerCharacter::AddHealthPoints(float addValue)
@ -207,26 +233,6 @@ void AExoPlayerCharacter::AddHealthPoints(float addValue)
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
{
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;
if (!bCapsuleRelative)

View File

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

View File

@ -5,6 +5,7 @@
#include "CoreMinimal.h"
#include "Camera/CameraComponent.h"
#include "Characters/ExoCharacterBase.h"
#include "Components/TimelineComponent.h"
#include "ExoPlayerCharacter.generated.h"
class UInteractionComponent;
@ -79,6 +80,9 @@ public:
*/
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "Camera")
float LowEyeHeightOffset;
UPROPERTY(EditAnywhere)
TObjectPtr<UCurveFloat> CapsuleResizeCurve;
/// U FUNCTIONS ///
@ -101,16 +105,6 @@ public:
UFUNCTION()
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")
void SetEyePositionOffsetTarget(FVector LocationOffset);
@ -125,10 +119,7 @@ public:
void SetTargetEyeHeight(float NewEyeHeight, const bool bCapsuleRelative = false);
UFUNCTION(BlueprintCallable, Category="Camera")
float GetCurrentEyeHeight(const bool bCapsuleRelative = false);
//UFUNCTION(BlueprintCallable, Category="Camera")
//float GetCurrentEyeHeightBase(const bool bCapsuleRelative = false);
float GetCurrentEyeHeight(const bool bCapsuleRelative = false) const;
UFUNCTION(BlueprintPure, Category="Camera")
float GetStandingEyeHeight(const bool bCapsuleRelative = false) const;
@ -170,6 +161,14 @@ private:
float TargetEyeHeight;
float EyeHeight;
FTimeline CrouchTimeline;
UFUNCTION()
void CrouchingUpdate(float Alpha);
UFUNCTION()
void CrouchingFinished();
void UpdateCameraHeight(float DeltaTime);
void ApplyCameraOffsets(float DeltaTime);
};

View File

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