기본 위젯 활용
TextBlock, Image, Button, ProgressBar 등 UMG의 핵심 리프 위젯을 C++과 블루프린트에서 효과적으로 사용하는 방법을 학습합니다.
TextBlock과 RichTextBlock
텍스트 표시의 기본과 서식 지정
UTextBlock은 단일 스타일의 텍스트를 표시하는 가장 기본적인 위젯이고, URichTextBlock은 인라인 마크업으로 여러 스타일을 혼합할 수 있는 고급 텍스트 위젯입니다.
// .h 파일 - BindWidget으로 블루프린트 위젯 참조
UPROPERTY(meta = (BindWidget))
UTextBlock* PlayerNameText;
UPROPERTY(meta = (BindWidget))
UTextBlock* ScoreText;
// .cpp 파일 - 텍스트 설정
void UMyHUD::UpdatePlayerInfo(const FString& Name, int32 Score)
{
PlayerNameText->SetText(FText::FromString(Name));
// FText::Format으로 로컬라이제이션 지원 포맷팅
ScoreText->SetText(FText::Format(
NSLOCTEXT("HUD", "ScoreFormat", "점수: {0}"),
FText::AsNumber(Score)
));
// 폰트 크기 동적 변경
FSlateFontInfo FontInfo = ScoreText->GetFont();
FontInfo.Size = 24;
ScoreText->SetFont(FontInfo);
// 색상 변경
ScoreText->SetColorAndOpacity(FSlateColor(FLinearColor::Yellow));
}
meta = (BindWidget)은 블루프린트 Widget Blueprint에서 같은 이름의 위젯을 자동으로 바인딩합니다. 위젯 이름이 일치하지 않으면 컴파일 에러가 발생합니다. 선택적 바인딩은 meta = (BindWidgetOptional)을 사용하세요.
RichTextBlock - 인라인 스타일
// Data Table 기반 스타일 시트 + 마크업
// "Default", "Bold", "Damage" 등의 행을 가진 DataTable 필요
// 블루프린트에서 RichTextBlock 텍스트 설정:
"적에게 <Bold>치명타</> <Damage>1,500</> 데미지!"
// C++에서 설정:
RichText->SetText(FText::FromString(
"적에게 <Bold>치명타</> <Damage>1,500</> 데미지!"
));
Image 위젯
텍스처, 머티리얼, 브러시를 활용한 이미지 표시
UImage 위젯은 텍스처, 머티리얼 인스턴스, 또는 Slate 브러시를 화면에 렌더링합니다. 게임 UI에서 아이콘, 배경, 장식 요소 등에 광범위하게 사용됩니다.
UPROPERTY(meta = (BindWidget))
UImage* IconImage;
void UItemSlot::SetItemIcon(UTexture2D* Texture)
{
if (Texture)
{
// 텍스처를 브러시로 설정
IconImage->SetBrushFromTexture(Texture);
// 브러시 크기 지정
IconImage->SetDesiredSizeOverride(FVector2D(64.f, 64.f));
}
}
void UItemSlot::SetRarityBorder(UMaterialInterface* RarityMat)
{
// 머티리얼 인스턴스를 이미지 브러시로 사용
IconImage->SetBrushFromMaterial(RarityMat);
}
void UItemSlot::SetTintColor(FLinearColor Color)
{
// 브러시 틴트 컬러 변경
IconImage->SetColorAndOpacity(Color);
}
void UItemSlot::SetFromSlateBrush()
{
// 코드에서 직접 브러시 구성
FSlateBrush Brush;
Brush.ImageSize = FVector2D(64.f, 64.f);
Brush.TintColor = FSlateColor(FLinearColor::White);
Brush.DrawAs = ESlateBrushDrawType::Image;
IconImage->SetBrush(Brush);
}
Image 위젯에 Dynamic Material Instance를 설정하면 셰이더 파라미터를 조작하여 GPU 기반 애니메이션을 만들 수 있습니다. 글로우 효과, 스크롤링 배경, 디졸브 전환 등에 활용하면 CPU 비용 없이 시각 효과를 구현할 수 있습니다.
Button과 상호작용 위젯
버튼 클릭, 체크박스, 슬라이더 이벤트 처리
// .h 파일
UPROPERTY(meta = (BindWidget))
UButton* StartButton;
UPROPERTY(meta = (BindWidget))
UButton* SettingsButton;
UFUNCTION()
void OnStartClicked();
UFUNCTION()
void OnSettingsHovered();
// .cpp 파일 - NativeConstruct에서 바인딩
void UMainMenu::NativeConstruct()
{
Super::NativeConstruct();
// 클릭 이벤트 바인딩
StartButton->OnClicked.AddDynamic(this, &UMainMenu::OnStartClicked);
// 호버 이벤트 바인딩
SettingsButton->OnHovered.AddDynamic(this, &UMainMenu::OnSettingsHovered);
}
void UMainMenu::OnStartClicked()
{
// 버튼 스타일 변경
FButtonStyle Style = StartButton->GetStyle();
Style.Normal.TintColor = FSlateColor(FLinearColor::Green);
StartButton->SetStyle(Style);
// 게임 시작 로직
GetWorld()->ServerTravel("/Game/Maps/GameLevel");
}
CheckBox와 Slider
UPROPERTY(meta = (BindWidget))
UCheckBox* VSyncCheckBox;
UPROPERTY(meta = (BindWidget))
USlider* VolumeSlider;
void USettingsWidget::NativeConstruct()
{
Super::NativeConstruct();
// CheckBox 상태 변경 이벤트
VSyncCheckBox->OnCheckStateChanged.AddDynamic(
this, &USettingsWidget::OnVSyncChanged);
// Slider 값 변경 이벤트
VolumeSlider->OnValueChanged.AddDynamic(
this, &USettingsWidget::OnVolumeChanged);
// 초기값 설정
VolumeSlider->SetValue(0.8f);
VolumeSlider->SetMinValue(0.0f);
VolumeSlider->SetMaxValue(1.0f);
}
void USettingsWidget::OnVSyncChanged(bool bIsChecked)
{
// CVar로 VSync 설정 변경
auto* Settings = GEngine->GetGameUserSettings();
Settings->SetVSyncEnabled(bIsChecked);
Settings->ApplySettings(false);
}
void USettingsWidget::OnVolumeChanged(float Value)
{
// Sound Mix를 통한 볼륨 조절
USoundMix* MasterMix = /* Sound Mix 에셋 참조 */;
UGameplayStatics::SetSoundMixClassOverride(
this, MasterMix, MasterSoundClass, Value, 1.0f, 0.1f);
}
ProgressBar와 동적 UI
게이지, 로딩바, 쿨다운 등 동적 피드백 위젯
UPROPERTY(meta = (BindWidget))
UProgressBar* HealthBar;
UPROPERTY(meta = (BindWidget))
UProgressBar* CooldownBar;
void UGameHUD::UpdateHealth(float Current, float Max)
{
float Percent = (Max > 0.f) ? Current / Max : 0.f;
HealthBar->SetPercent(Percent);
// HP에 따른 색상 변경
FLinearColor BarColor;
if (Percent > 0.5f)
BarColor = FLinearColor::Green;
else if (Percent > 0.25f)
BarColor = FLinearColor(1.f, 0.5f, 0.f); // 주황
else
BarColor = FLinearColor::Red;
HealthBar->SetFillColorAndOpacity(BarColor);
}
// 쿨다운 바: 타이머 기반 업데이트
void UGameHUD::StartCooldown(float Duration)
{
CooldownDuration = Duration;
CooldownRemaining = Duration;
bCooldownActive = true;
}
void UGameHUD::NativeTick(const FGeometry& Geometry, float DeltaTime)
{
Super::NativeTick(Geometry, DeltaTime);
if (bCooldownActive)
{
CooldownRemaining -= DeltaTime;
float Pct = FMath::Clamp(CooldownRemaining / CooldownDuration, 0.f, 1.f);
CooldownBar->SetPercent(Pct);
if (CooldownRemaining <= 0.f)
bCooldownActive = false;
}
}
NativeTick()은 매 프레임 호출되므로 성능에 영향을 줍니다. 쿨다운처럼 지속적인 업데이트가 필요한 경우에만 사용하고, HP 변경처럼 이벤트 기반으로 처리 가능한 경우에는 델리게이트/이벤트 디스패처를 통해 필요한 시점에만 업데이트하세요.
Tick 기반 (비효율적)
// 매 프레임 체크 - 불필요한 비용
void NativeTick(...)
{
float HP = Character->GetHP();
HealthBar->SetPercent(HP / MaxHP);
}
이벤트 기반 (효율적)
// HP 변경 시에만 업데이트
Character->OnHPChanged.AddDynamic(
this, &UGameHUD::UpdateHealth
);
핵심 요약
meta = (BindWidget)으로 C++ 코드에서 블루프린트 위젯을 안전하게 참조할 수 있습니다- TextBlock은
FText::Format으로 로컬라이제이션을 지원하고, RichTextBlock은 인라인 마크업으로 복합 스타일을 적용합니다 - Image 위젯은 텍스처, 머티리얼, Slate 브러시를 모두 지원하며 Dynamic Material Instance로 GPU 애니메이션이 가능합니다
- Button의 OnClicked/OnHovered 델리게이트에 바인딩하여 상호작용을 처리합니다
- 지속적 업데이트에는 Tick을, 상태 변경에는 델리게이트/이벤트 기반 패턴을 사용하여 성능을 최적화합니다
도전 과제
배운 내용을 직접 실습해보세요
DataTable 기반 RichTextBlock 스타일 시트를 만들고, <bold>, <highlight>, <damage> 등의 커스텀 태그로 게임 내 대화 텍스트를 다양하게 꾸며 보세요. 인라인 이미지(아이템 아이콘)도 추가합니다.
UProgressBar의 FillImage를 커스텀 머티리얼로 교체하고, C++에서 SetPercent()와 SetFillColorAndOpacity()를 사용하여 HP가 낮아질수록 색상이 변하는 체력바를 구현해 보세요.
TextBlock + Image + ProgressBar를 조합한 '스킬 슬롯' UserWidget을 만들고, 쿨다운 표시(원형 와이프), 스킬 레벨 텍스트, 아이콘을 모두 포함하는 재사용 가능한 컴포넌트를 완성하세요.