2024.08.22
이번 글에서는 PickUpDefense 게임의 UI 위젯 시스템에 대한 개념을 정리하고, 제네릭 함수를 활용하여 코드 중복을 줄이는 과정을 다룹니다. 특히, 언리얼 엔진의 UMG(User Interface) 시스템에서 위젯을 생성하고 배치하는 방법에 대해 설명합니다.
언리얼 엔진에서 위젯(Widget)은 게임의 사용자 인터페이스(UI)를 구성하는 기본 요소입니다. UMG(User Interface Design) 시스템을 통해 HUD(Heads-Up Display), 메뉴, 버튼, 텍스트, 이미지 등 다양한 UI 요소를 디자인하고 배치할 수 있습니다.
UCanvasPanel
, UHorizontalBox
, UVerticalBox
등이 있습니다.UHorizontalBoxSlot
, UVerticalBoxSlot
등이 있습니다.WidgetTree
는 위젯 트리를 구성하고 관리하는 데 사용됩니다.PickUpDefense에서는 다양한 UI 위젯을 사용하여 게임의 인터페이스를 구성하고 있습니다. 이 과정에서 위젯을 효율적으로 생성하고 관리하기 위해 C++을 활용하였습니다.
void UYourWidgetClass::SomeFunction()
{
// UHorizontalBox 생성
UHorizontalBox* HorizontalBox = WidgetTree->ConstructWidget<UHorizontalBox>(UHorizontalBox::StaticClass(), TEXT("HorizontalBox"));
// UBorder 생성 및 배치
UBorder* Border = WidgetTree->ConstructWidget<UBorder>(UBorder::StaticClass(), TEXT("ExampleBorder"));
Border->SetBrushColor(FLinearColor(0.735351f, 0.35115f, 1.0f, 0.4f));
// UHorizontalBoxSlot에 UBorder 추가
if (HorizontalBox)
{
UHorizontalBoxSlot* Slot = HorizontalBox->AddChildToHorizontalBox(Border);
if (Slot)
{
FSlateChildSize ChildSize;
ChildSize.Value = 1.0f;
Slot->SetSize(ChildSize);
Slot->SetHorizontalAlignment(EHorizontalAlignment::HAlign_Fill);
Slot->SetVerticalAlignment(EVerticalAlignment::VAlign_Fill);
Slot->SetPadding(FMargin(1.0f, 0.0f, 1.0f, 0.0f));
}
}
}
WidgetTree->ConstructWidget
메서드를 사용하여 위젯을 생성합니다.Slot
을 통해 레이아웃 속성을 설정합니다.여러 부모 위젯에 공통적인 작업을 수행하는 코드를 제네릭 함수로 구현함으로써 코드 중복을 줄이고 유지보수성을 높일 수 있습니다. 예를 들어, UHorizontalBox
와 UVerticalBox
모두에 UBorder
위젯을 추가하는 작업을 제네릭 함수로 일반화할 수 있습니다.
template <typename TParentWidget>
void AddBorderToChild(TParentWidget* ParentWidget, UWidgetTree* WidgetTree, const FName& BorderName)
{
UBorder* Border = WidgetTree->ConstructWidget<UBorder>(UBorder::StaticClass(), BorderName);
Border->SetBrushColor(FLinearColor(0.735351f, 0.35115f, 1.0f, 0.4f));
if (ParentWidget)
{
UPanelSlot* PanelSlot = ParentWidget->AddChild(Border);
if (PanelSlot)
{
// 슬롯 타입에 따라 적절한 설정 적용
if (UHorizontalBoxSlot* HorizontalSlot = Cast<UHorizontalBoxSlot>(PanelSlot))
{
HorizontalSlot->SetSize(FSlateChildSize(ESlateSizeRule::Fill));
HorizontalSlot->SetHorizontalAlignment(EHorizontalAlignment::HAlign_Fill);
HorizontalSlot->SetVerticalAlignment(EVerticalAlignment::VAlign_Fill);
HorizontalSlot->SetPadding(FMargin(1.0f, 0.0f, 1.0f, 0.0f));
}
else if (UVerticalBoxSlot* VerticalSlot = Cast<UVerticalBoxSlot>(PanelSlot))
{
VerticalSlot->SetSize(FSlateChildSize(ESlateSizeRule::Fill));
VerticalSlot->SetHorizontalAlignment(EHorizontalAlignment::HAlign_Fill);
VerticalSlot->SetVerticalAlignment(EVerticalAlignment::VAlign_Fill);
VerticalSlot->SetPadding(FMargin(1.0f, 0.0f, 1.0f, 0.0f));
}
}
}
}
FName
은 언리얼 엔진에서 고유 식별자로 사용되며, 위젯을 생성할 때 유용합니다. 동적으로 생성되는 위젯에 고유한 이름을 부여하기 위해 FName
과 FString
을 결합하여 새로운 FName
을 생성하는 방법을 사용했습니다.
FName CreateDynamicFName(const FName& BaseName, int32 Index)
{
return FName(*FString::Printf(TEXT("%s_%d"), *BaseName.ToString(), Index));
}
FName
을 생성합니다.PickUpDefense의 UI 위젯 시스템 구현 과정에서 위젯의 개념을 이해하고, 제네릭 함수와 FName
을 활용하여 코드의 효율성을 크게 향상시켰습니다.
앞으로의 작업에서는 이러한 기반을 바탕으로 PickUpDefense 게임의 UI 시스템을 더욱 발전시키고, 게임의 주요 메커니즘을 구현해 나갈 예정입니다. 다음 단계에서는 게임의 전반적인 인터페이스를 완성하고, 플레이어 경험을 개선할 수 있는 작업들을 진행할 계획입니다.
이 글이 PickUpDefense 게임의 개발 과정을 이해하는 데 도움이 되길 바라며, 앞으로의 개발 과정에서도 이러한 경험이 바탕이 되어 더욱 발전된 기능을 구현할 수 있기를 기대합니다. 피드백이나 질문이 있으면 언제든지 남겨주세요!