캐릭터 스태미나 시스템

GwakItect·2025년 8월 1일

Shooter Game Project

목록 보기
6/9

Stamina


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();
}




스태미나 시스템 로직


  1. 관련 프로퍼티
이름타입역할
MaxStaminafloat최대 스태미나 양. (기본값: 100)
CurrentStaminafloat현재 스태미나 양. BeginPlay에서 MaxStamina로 초기화
StaminaConsumeRatefloat초당 소모되는 스태미나 양 (30.f)
StaminaRegenerationRatefloat초당 회복되는 스태미나 양 (20.f)
StaminaRegenDelayfloat달리기를 멈춘 후, 스태미나 회복이 시작되기까지의 대기 시간(초)
MinStaminafloatSprint에 필요한 최소 스태미나 양
StaminaRegenTimerHandleFTimerHandle스태미나 회복 딜레이 타이머 핸들
bCanRegenerateStaminabool스태미나 회복 가능 상태 플래그
  1. 스태미나 시스템 로직 (Tick 및 Timer 사용)
  • BeginPlay: CurrentStaminaMaxStamina로 초기화
  • StartSprint: 달리기 시작 조건을 (최소 스태미나, 전방 이동) 확인 후 조건 충족 시 스태미나 회복 타이머를 중지시키고 bCanRegenerateStaminafalse로 설정
  • StopSprint: 달리기를 멈추면, StaminaRegenerationDelay초 후에 StartStaminaRegeneration 함수를 호출하는 타이머를 시작
  • Tick:
    • 달리는 중 (Sprinting 상태): StaminaConsumptionRate에 따라 CurrentStamina를 매 프레임 감소. 스태미나가 0이 되면 StopSprint()를 강제 호출
    • 달리지 않는 중: bCanRegenerateStaminatrue일 때, StaminaRegenerationRate에 따라 CurrentStamina를 매 프레임 증가
    • 값 보정: FMath::Clamp를 사용해 CurrentStamina가 항상 0과 MaxStamina 사이를 유지
  • StartStaminaRegeneration: StopSprint에서 시작된 타이머에 의해 호출되며, bCanRegenerateStamina 값을 true로 변경해 스태미나 회복을 시작하도록 허용

0개의 댓글