Shift 입력과 W(X) 입력이 들어오면 캐릭터가 Sprinting 상태로 전환되면서 이동속도가 1.5배 빨라진다. 캐릭터가 무한으로 Sprint 할 수 없도록 Stamina 속성을 생성하여 해당 자원을 모두 소모할 시 일시적으로 달리지 못하도록 설정하는 로직을 추가한다.
헤더 파일
// ----- 스태미나 -----
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "State|Stamina")
float MaxStamina;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "State|Stamina")
float CurrentStamina;
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "State|Stamina")
float StaminaRegenRate = 20.f; // 스태미나 회복량
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "State|Stamina")
float StaminaComsumeRate = 30.f; // 스태미나 소모량
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "State|Stamina")
float StaminaRegenTimer = 3.f; // 스태미나 회복 딜레이
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "State|Stamina")
float MinStamina = 10.f; // 최소 스태미나
FTimerHandle StaminaRegenTimerHandle; // 스태미나 회복 딜레이 핸들
bool bCanStaminaRegen;
void StartStaminaRegen();
// ---------------------
소스 파일 - 생성자 혹은 BeginPlay 함수
MaxStamina = 100;
CurrentStamina = MaxStamina;
bCanStaminaRegen = true;
소스 파일 - Tick 함수
// ----- 스태미나 로직 -----
if (CurrentState == ECharacterState::Sprinting)
{
CurrentStamina -= DeltaTime * StaminaComsumeRate;
if (CurrentStamina <= 0 || LastInputVector.X <= 0.f)
{
StopSprint();
}
}
else
{
if (bCanStaminaRegen)
{
CurrentStamina += DeltaTime * StaminaRegenRate;
}
}
CurrentStamina = FMath::Clamp(CurrentStamina, 0.f, MaxStamina);
// -------------------------
소스 파일 - 추가 함수
void UAttributeComponent::StartStaminaRegen()
{
bCanStaminaRegen = true;
}
소스 파일 -
void AMyCharacter::StartSprint()
{
if (CurrentStamina < MinStamina || LastInputVector.X <= 0.f)
{
return;
}
bWantsToSprint = true;
if (CurrentState == ECharacterState::Jumping || bIsZoomed || bIsCrouching)
{
return;
}
if (GetCharacterMovement())
{
if (GetCharacterMovement()->IsFalling())
{
return;
}
bCanStaminaRegen = false;
GetWorld()->GetTimerManager().ClearTimer(StaminaRegenTimerHandle);
SetCharacterState(ECharacterState::Sprinting);
SprintFOVTimeline->PlayFromStart();
}
}
void AMyCharacter::StopSprint()
{
bWantsToSprint = false;
if (CurrentState != ECharacterState::Sprinting)
{
return;
}
GetWorld()->GetTimerManager().SetTimer(StaminaRegenTimerHandle, this, &AMyCharacter::StartStaminaRegen, StaminaRegenTimer, false);
SprintFOVTimeline->Reverse();
UpdateGroundState();
}
| 이름 | 타입 | 역할 |
|---|---|---|
MaxStamina | float | 최대 스태미나 양. (기본값: 100) |
CurrentStamina | float | 현재 스태미나 양. BeginPlay에서 MaxStamina로 초기화 |
StaminaConsumeRate | float | 초당 소모되는 스태미나 양 (30.f) |
StaminaRegenerationRate | float | 초당 회복되는 스태미나 양 (20.f) |
StaminaRegenDelay | float | 달리기를 멈춘 후, 스태미나 회복이 시작되기까지의 대기 시간(초) |
MinStamina | float | Sprint에 필요한 최소 스태미나 양 |
StaminaRegenTimerHandle | FTimerHandle | 스태미나 회복 딜레이 타이머 핸들 |
bCanRegenerateStamina | bool | 스태미나 회복 가능 상태 플래그 |
BeginPlay: CurrentStamina를 MaxStamina로 초기화StartSprint: 달리기 시작 조건을 (최소 스태미나, 전방 이동) 확인 후 조건 충족 시 스태미나 회복 타이머를 중지시키고 bCanRegenerateStamina를 false로 설정StopSprint: 달리기를 멈추면, StaminaRegenerationDelay초 후에 StartStaminaRegeneration 함수를 호출하는 타이머를 시작Tick:Sprinting 상태): StaminaConsumptionRate에 따라 CurrentStamina를 매 프레임 감소. 스태미나가 0이 되면 StopSprint()를 강제 호출bCanRegenerateStamina가 true일 때, StaminaRegenerationRate에 따라 CurrentStamina를 매 프레임 증가FMath::Clamp를 사용해 CurrentStamina가 항상 0과 MaxStamina 사이를 유지StartStaminaRegeneration: StopSprint에서 시작된 타이머에 의해 호출되며, bCanRegenerateStamina 값을 true로 변경해 스태미나 회복을 시작하도록 허용