HUD 클래스 활용
HUD(Heads-Up Display)는 게임 내에서 플레이어에게 중요한 정보를 표시하는 데 사용되는 UI 요소입니다.
언리얼 엔진에서는 AHUD
클래스를 통해 HUD를 구현할 수 있습니다.
AHUD 클래스의 주요 기능과 특징
AHUD
클래스는 다음과 같은 주요 기능을 제공합니다.
- 2D 그래픽 요소 그리기
- 게임 정보 표시
- UMG 위젯과의 통합
- 입력 처리
UCLASS()
class MYPROJECT_API AMyHUD : public AHUD
{
GENERATED_BODY()
public:
AMyHUD();
virtual void DrawHUD() override;
virtual void BeginPlay() override;
private:
UPROPERTY()
class UUserWidget* MainWidget;
};
HUD에 2D 그래픽 요소 그리기
DrawHUD
함수를 오버라이드하여 2D 그래픽 요소를 그릴 수 있습니다.
void AMyHUD::DrawHUD()
{
Super::DrawHUD();
// 십자선 그리기
float CrosshairSize = 10.0f;
float ScreenCenterX = Canvas->SizeX / 2;
float ScreenCenterY = Canvas->SizeY / 2;
DrawLine(ScreenCenterX - CrosshairSize, ScreenCenterY, ScreenCenterX + CrosshairSize, ScreenCenterY, FLinearColor::Red);
DrawLine(ScreenCenterX, ScreenCenterY - CrosshairSize, ScreenCenterX, ScreenCenterY + CrosshairSize, FLinearColor::Red);
// 텍스트 그리기
DrawText(FString("Hello, HUD!"), FLinearColor::White, 50, 50, nullptr, 1.5f);
}
HUD를 통한 게임 정보 표시
플레이어의 체력, 점수 등의 게임 정보를 HUD에 표시할 수 있습니다.
void AMyHUD::DrawHUD()
{
Super::DrawHUD();
APlayerController* PC = GetOwningPlayerController();
if (PC)
{
AMyPlayerState* PS = PC->GetPlayerState<AMyPlayerState>();
if (PS)
{
FString HealthText = FString::Printf(TEXT("Health: %d"), FMath::RoundToInt(PS->GetHealth()));
DrawText(HealthText, FLinearColor::Green, 50, 100, nullptr, 1.5f);
FString ScoreText = FString::Printf(TEXT("Score: %d"), PS->GetScore());
DrawText(ScoreText, FLinearColor::Yellow, 50, 150, nullptr, 1.5f);
}
}
}
HUD와 UMG 위젯의 통합
HUD 클래스에서 UMG 위젯을 생성하고 관리할 수 있습니다.
void AMyHUD::BeginPlay()
{
Super::BeginPlay();
if (MainWidgetClass)
{
MainWidget = CreateWidget<UUserWidget>(GetOwningPlayerController(), MainWidgetClass);
if (MainWidget)
{
MainWidget->AddToViewport();
}
}
}
동적 HUD 요소 생성 및 관리
게임 상황에 따라 동적으로 HUD 요소를 생성하고 관리할 수 있습니다.
void AMyHUD::ShowDamageIndicator(float DamageAmount, FVector DamageLocation)
{
FVector2D ScreenLocation;
if (ProjectWorldLocationToScreen(DamageLocation, ScreenLocation))
{
UDamageIndicatorWidget* DamageWidget = CreateWidget<UDamageIndicatorWidget>(GetOwningPlayerController(), DamageIndicatorClass);
if (DamageWidget)
{
DamageWidget->SetDamageAmount(DamageAmount);
DamageWidget->SetPositionInViewport(ScreenLocation);
DamageWidget->AddToViewport();
}
}
}
플레이어 상태에 따른 HUD 업데이트
플레이어의 상태 변화에 따라 HUD를 업데이트할 수 있습니다.
void AMyHUD::UpdatePlayerStatus(float Health, int32 Ammo)
{
if (MainWidget)
{
UMyMainWidget* MyMainWidget = Cast<UMyMainWidget>(MainWidget);
if (MyMainWidget)
{
MyMainWidget->UpdateHealthBar(Health);
MyMainWidget->UpdateAmmoCount(Ammo);
}
}
}
HUD를 활용한 고급 기능 구현
조준점
void AMyHUD::DrawCrosshair()
{
float CrosshairSize = 10.0f;
float ScreenCenterX = Canvas->SizeX / 2;
float ScreenCenterY = Canvas->SizeY / 2;
DrawLine(ScreenCenterX - CrosshairSize, ScreenCenterY, ScreenCenterX + CrosshairSize, ScreenCenterY, FLinearColor::Green, 2.0f);
DrawLine(ScreenCenterX, ScreenCenterY - CrosshairSize, ScreenCenterX, ScreenCenterY + CrosshairSize, FLinearColor::Green, 2.0f);
}
미니맵
미니맵은 주로 UMG 위젯을 사용하여 구현하지만, HUD에서 직접 그릴 수도 있습니다.
void AMyHUD::DrawMinimap()
{
float MinimapSize = 200.0f;
float MinimapX = Canvas->SizeX - MinimapSize - 20.0f;
float MinimapY = 20.0f;
DrawRect(FLinearColor(0, 0, 0, 0.5f), MinimapX, MinimapY, MinimapSize, MinimapSize);
// 플레이어와 적의 위치를 미니맵에 표시
// ...
}
데미지 표시기
void AMyHUD::ShowDamageDirection(FVector DamageLocation)
{
APlayerController* PC = GetOwningPlayerController();
if (PC)
{
FVector PlayerLocation = PC->GetPawn()->GetActorLocation();
FVector DamageDirection = (DamageLocation - PlayerLocation).GetSafeNormal();
float Angle = FMath::Atan2(DamageDirection.Y, DamageDirection.X);
float ScreenAngle = Angle * (180.0f / PI) + 90.0f;
float IndicatorSize = 50.0f;
float ScreenCenterX = Canvas->SizeX / 2;
float ScreenCenterY = Canvas->SizeY / 2;
float IndicatorDistance = FMath::Min(ScreenCenterX, ScreenCenterY) * 0.8f;
FVector2D IndicatorPos(
ScreenCenterX + IndicatorDistance * FMath::Cos(Angle),
ScreenCenterY + IndicatorDistance * FMath::Sin(Angle)
);
DrawText(TEXT(">"), FLinearColor::Red, IndicatorPos.X, IndicatorPos.Y, nullptr, 2.0f, ScreenAngle);
}
}
HUD의 성능 최적화 전략
- 캐싱 : 자주 사용하는 값들을 캐싱하여 매 프레임마다의 계산을 줄입니다.
- 드로우 콜 최소화 : 가능한 한 드로우 콜을 줄이도록 HUD 요소를 설계합니다.
- 클리핑 : 화면 밖의 요소는 그리지 않도록 합니다.
void AMyHUD::DrawHUD()
{
Super::DrawHUD();
// 성능 최적화를 위한 캐싱
static float CachedScreenWidth = Canvas->SizeX;
static float CachedScreenHeight = Canvas->SizeY;
// 화면 크기가 변경되었을 때만 업데이트
if (Canvas->SizeX != CachedScreenWidth || Canvas->SizeY != CachedScreenHeight)
{
CachedScreenWidth = Canvas->SizeX;
CachedScreenHeight = Canvas->SizeY;
// 화면 크기에 따른 계산 수행
// ...
}
// 클리핑을 이용한 최적화
FVector2D PlayerPos = GetPlayerScreenPosition();
if (PlayerPos.X >= 0 && PlayerPos.X <= CachedScreenWidth &&
PlayerPos.Y >= 0 && PlayerPos.Y <= CachedScreenHeight)
{
DrawPlayerIndicator(PlayerPos);
}
}
다양한 해상도에 대응하는 HUD 디자인
void AMyHUD::DrawHUD()
{
Super::DrawHUD();
float ScreenWidth = Canvas->SizeX;
float ScreenHeight = Canvas->SizeY;
float ScaleFactor = FMath::Min(ScreenWidth / 1920.0f, ScreenHeight / 1080.0f);
// 해상도에 따라 스케일 조정
float ScaledSize = 100.0f * ScaleFactor;
FVector2D Position(ScreenWidth - ScaledSize - 20.0f, 20.0f);
DrawTexture(SomeTexture, Position.X, Position.Y, ScaledSize, ScaledSize, 0, 0, 1, 1);
}
HUD와 게임플레이 시스템의 연동
게임플레이 이벤트에 따라 HUD를 업데이트하기 위해 델리게이트를 사용할 수 있습니다.
// AMyPlayerController.h
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnHealthChangedSignature, float, NewHealth);
UCLASS()
class MYPROJECT_API AMyPlayerController : public APlayerController
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintAssignable, Category = "Events")
FOnHealthChangedSignature OnHealthChanged;
// ...
};
// AMyHUD.cpp
void AMyHUD::BeginPlay()
{
Super::BeginPlay();
AMyPlayerController* PC = Cast<AMyPlayerController>(GetOwningPlayerController());
if (PC)
{
PC->OnHealthChanged.AddDynamic(this, &AMyHUD::OnHealthChanged);
}
}
void AMyHUD::OnHealthChanged(float NewHealth)
{
// HUD 업데이트 로직
}
디버깅 팁
- 화면에 디버그 정보 표시
void AMyHUD::DrawHUD()
{
Super::DrawHUD();
##if !UE_BUILD_SHIPPING
// 디버그 모드에서만 표시
DrawText(FString::Printf(TEXT("Debug: FPS: %.2f"), GetWorld()->GetFPS()), FLinearColor::Yellow, 10, 10);
##endif
}
- 로깅 사용
void AMyHUD::SomeFunction()
{
UE_LOG(LogTemp, Warning, TEXT("SomeFunction called with value: %d"), SomeValue);
}
- 비주얼 디버깅
void AMyHUD::DrawHUD()
{
Super::DrawHUD();
##if !UE_BUILD_SHIPPING
// HUD 요소의 경계를 시각화
DrawRect(FLinearColor::Red, 100, 100, 200, 100);
##endif
}
HUD 클래스는 게임의 시각적 정보를 플레이어에게 효과적으로 전달하는 중요한 역할을 합니다. C++에서 AHUD 클래스를 활용하면 높은 수준의 커스터마이징과 최적화가 가능합니다. UMG 위젯과의 통합, 동적 HUD 요소 관리, 그리고 게임플레이 시스템과의 연동을 통해 풍부하고 반응성 높은 사용자 인터페이스를 구현할 수 있습니다. 성능 최적화와 다양한 해상도 대응을 고려하여 HUD를 설계하면, 모든 플레이어에게 일관된 경험을 제공할 수 있습니다.