Hi. There is no mesh on the character, only the capsule and a camera located on the spring arm that is connected to a camera root scene component. I set the shrink value of the capsule by a ratio at the BeginPlay(), and the function below sets the CrouchedEyeHeight by a ratio of 0.8 with the default engine function.
void UCustomMovementComponent::BeginPlay()
{
Super::BeginPlay();
if (IsValid(CharacterOwner))
{
DefaultEyeHeight = CharacterOwner->BaseEyeHeight;
StandingHalfHeight = CharacterOwner->GetCapsuleComponent()->GetUnscaledCapsuleHalfHeight();
SetCrouchedHalfHeight(StandingHalfHeight * CrouchRatio);
TargetHalfHeight = StandingHalfHeight;
}
}
void UCharacterMovementComponent::SetCrouchedHalfHeight(const float NewValue)
{
CrouchedHalfHeight = NewValue;
if (CharacterOwner != nullptr)
{
CharacterOwner->RecalculateCrouchedEyeHeight();
}
}
void ACharacter::RecalculateCrouchedEyeHeight()
{
if (CharacterMovement != nullptr)
{
constexpr float EyeHeightRatio = 0.8f;
CrouchedEyeHeight = CharacterMovement->GetCrouchedHalfHeight() * EyeHeightRatio;
}
}
And with another function below I trigger crouching and do the corresponding value redirects.
void UCustomMovementComponent::ToggleCrouching(const bool bCrouch)
{
if (IsValid(CharacterOwner) && !IsSprinting())
{
TargetHalfHeight = bCrouch ? GetCrouchedHalfHeight() : StandingHalfHeight;
TargetEyeHeight = bCrouch ? CharacterOwner->CrouchedEyeHeight : DefaultEyeHeight;
}
}
Then, the necessary interpolations are made in Tick() with the updated values.
void UCustomMovementComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
if (!IsValid(CharacterOwner)) return;
if (UCapsuleComponent* capsule = CharacterOwner->GetCapsuleComponent())
{
CurrentHalfHeight = capsule->GetUnscaledCapsuleHalfHeight();
if (FMath::Abs(CurrentHalfHeight - TargetHalfHeight) < 0.1f)
{
CurrentHalfHeight = TargetHalfHeight;
capsule->SetCapsuleHalfHeight(TargetHalfHeight);
CharacterOwner->BaseEyeHeight = TargetEyeHeight;
return;
}
capsule->SetCapsuleHalfHeight(FMath::FInterpTo(CurrentHalfHeight, TargetHalfHeight, DeltaTime, CrouchInterpSpeed));
CharacterOwner->BaseEyeHeight = FMath::FInterpTo(CharacterOwner->BaseEyeHeight, TargetEyeHeight, DeltaTime, CrouchInterpSpeed);
}
}
The camera which initially remains inside the capsule, ends up outside the capsule, on top, when we crouch down. Even though it updates at the same ratio, I still don’t get the desired result. Also, setting the BaseEyeHeight value does not make any difference.
Am I making a logical mistake here, or is there something else preventing this?