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 ;
};
Copy
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 );
}
Copy
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 );
}
}
}
Copy
HUD와 UMG 위젯의 통합
HUD 클래스에서 UMG 위젯을 생성하고 관리할 수 있습니다.
void AMyHUD :: BeginPlay ()
{
Super :: BeginPlay ();
if (MainWidgetClass)
{
MainWidget = CreateWidget < UUserWidget >( GetOwningPlayerController (), MainWidgetClass);
if (MainWidget)
{
MainWidget -> AddToViewport ();
}
}
}
Copy
동적 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 ();
}
}
}
Copy
플레이어 상태에 따른 HUD 업데이트
플레이어의 상태 변화에 따라 HUD를 업데이트할 수 있습니다.
void AMyHUD :: UpdatePlayerStatus ( float Health , int32 Ammo )
{
if (MainWidget)
{
UMyMainWidget* MyMainWidget = Cast < UMyMainWidget >(MainWidget);
if (MyMainWidget)
{
MyMainWidget -> UpdateHealthBar (Health);
MyMainWidget -> UpdateAmmoCount (Ammo);
}
}
}
Copy
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 );
}
Copy
미니맵
미니맵은 주로 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);
// 플레이어와 적의 위치를 미니맵에 표시
// ...
}
Copy
데미지 표시기
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);
}
}
Copy
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);
}
}
Copy
다양한 해상도에 대응하는 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 );
}
Copy
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 업데이트 로직
}
Copy
디버깅 팁
화면에 디버그 정보 표시
void AMyHUD :: DrawHUD ()
{
Super :: DrawHUD ();
##if !UE_BUILD_SHIPPING
// 디버그 모드에서만 표시
DrawText ( FString :: Printf ( TEXT ( "Debug: FPS: %.2f " ), GetWorld ()-> GetFPS ()), FLinearColor ::Yellow, 10 , 10 );
##endif
}
Copy
로깅 사용
void AMyHUD :: SomeFunction ()
{
UE_LOG (LogTemp, Warning, TEXT ( "SomeFunction called with value: %d " ), SomeValue);
}
Copy
비주얼 디버깅
void AMyHUD :: DrawHUD ()
{
Super :: DrawHUD ();
##if !UE_BUILD_SHIPPING
// HUD 요소의 경계를 시각화
DrawRect ( FLinearColor ::Red, 100 , 100 , 200 , 100 );
##endif
}
Copy
HUD 클래스는 게임의 시각적 정보를 플레이어에게 효과적으로 전달하는 중요한 역할을 합니다. C++에서 AHUD 클래스를 활용하면 높은 수준의 커스터마이징과 최적화가 가능합니다. UMG 위젯과의 통합, 동적 HUD 요소 관리, 그리고 게임플레이 시스템과의 연동을 통해 풍부하고 반응성 높은 사용자 인터페이스를 구현할 수 있습니다. 성능 최적화와 다양한 해상도 대응을 고려하여 HUD를 설계하면, 모든 플레이어에게 일관된 경험을 제공할 수 있습니다.