개요
오늘은 언리얼 엔진 5에서 캐릭터 체력 시스템과 점수 관리 시스템을 구현하는 방법을 정리해봤다.
싱글 플레이 환경을 기준으로, 체력과 점수를 어떻게 관리하고, 아이템과 상호작용하도록 설계하는지 살펴봤다.
배운 내용
SpartaCharacter)에 체력 변수를 넣어 관리하는 것이 효율적이다.UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Health")
float MaxHealth;
UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category = "Health")
float Health;
UFUNCTION(BlueprintPure, Category = "Health")
int32 GetHealth() const;
UFUNCTION(BlueprintCallable, Category = "Health")
void AddHealth(float Amount);
virtual float TakeDamage(float DamageAmount, struct FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser) override;
UFUNCTION(BlueprintCallable, Category = "Health")
virtual void OnDeath();
GetHealth() : 현재 체력을 반환
AddHealth(float Amount) : 체력을 회복 (최대 체력 초과 방지)
TakeDamage(float DamageAmount, ...) : 데미지 처리 (체력 감소 & 사망 체크)
OnDeath() : 체력이 0이 되면 실행되는 사망 처리 함수
ApplyDamage()와 TakeDamage()를 활용하면 쉽게 데미지 처리가 가능하다.AddHealth()를 이용해 회복 후 최대 체력을 초과하지 않도록 FMath::Clamp()를 사용했다.void ASpartaCharacter::AddHealth(float Amount)
{
Health = FMath::Clamp(Health + Amount, 0.0f, MaxHealth);
UE_LOG(LogTemp, Log, TEXT("Health increased to: %f"), Health);
}
float ASpartaCharacter::TakeDamage(float DamageAmount, FDamageEvent const& DamageEvent, AController* EventInstigator, AActor* DamageCauser)
{
float ActualDamage = Super::TakeDamage(DamageAmount, DamageEvent, EventInstigator, DamageCauser);
Health = FMath::Clamp(Health - DamageAmount, 0.0f, MaxHealth);
UE_LOG(LogTemp, Warning, TEXT("Health decreased to: %f"), Health);
if (Health <= 0.0f) { OnDeath(); }
return ActualDamage;
}
OnDeath())void ASpartaCharacter::OnDeath()
{
UE_LOG(LogTemp, Error, TEXT("Character is Dead!"));
// 사망 후 추가 로직 (예: 애니메이션, 리스폰 등)
}
MineItem) 데미지 처리ApplyDamage()를 호출해 주변 플레이어에게 폭발 데미지를 준다.void AMineItem::Explode()
{
TArray<AActor*> OverlappingActors;
ExplosionCollision->GetOverlappingActors(OverlappingActors);
for (AActor* Actor : OverlappingActors)
{
if (Actor && Actor->ActorHasTag("Player"))
{
UGameplayStatics::ApplyDamage(Actor, ExplosionDamage, nullptr, this, UDamageType::StaticClass());
}
}
DestroyItem();
}
HealingItem) 체력 회복AddHealth() 함수를 호출해 플레이어의 체력을 증가시킨다.void AHealingItem::ActivateItem(AActor* Activator)
{
if (Activator && Activator->ActorHasTag("Player"))
{
if (ASpartaCharacter* PlayerCharacter = Cast<ASpartaCharacter>(Activator))
{
PlayerCharacter->AddHealth(HealAmount);
}
DestroyItem();
}
}
GameMode는 게임 규칙을 관리하는 역할 (오직 서버에서만 존재)GameState는 게임 전역 데이터를 저장하는 역할 (서버와 클라이언트가 공유)UPROPERTY(VisibleAnywhere, BlueprintReadWrite, Category="Score")
int32 Score;
UFUNCTION(BlueprintPure, Category="Score")
int32 GetScore() const;
UFUNCTION(BlueprintCallable, Category="Score")
void AddScore(int32 Amount);
void ASpartaGameStateBase::AddScore(int32 Amount)
{
Score += Amount;
}
SpartaGameStateBase로 설정ASpartaGameMode::ASpartaGameMode()
{
GameStateClass = ASpartaGameStateBase::StaticClass();
}
BP_SpartaGameStateBaseCoinItem) 점수 획득 구현GetWorld()->GetGameState<ASpartaGameStateBase>() 를 사용해 GameState에 접근AddScore(PointValue) 호출해 점수 증가void ACoinItem::ActivateItem(AActor* Activator)
{
if (Activator && Activator->ActorHasTag("Player"))
{
if (UWorld* World = GetWorld())
{
if (ASpartaGameStateBase* GameState = World->GetGameState<ASpartaGameStateBase>())
{
GameState->AddScore(PointValue);
}
}
DestroyItem();
}
}
내용 정리
체력 시스템
TakeDamage()와 ApplyDamage()를 활용해 데미지 처리AddHealth()로 체력 회복, OnDeath()로 사망 처리(MineItem)과 힐링 아이템(HealingItem)이 체력에 영향을 주도록 구현점수 시스템
GameStateClass를 SpartaGameStateBase로 설정CoinItem에서 AddScore() 호출하여 점수 증가