Property Binding
UMG의 속성 바인딩 메커니즘, 함수 바인딩, 이벤트 기반 업데이트 패턴을 학습합니다.
UMG 속성 바인딩
블루프린트/C++에서 위젯 속성을 데이터에 연결하는 방법
UMG에서 위젯 속성을 게임 데이터와 연결하는 방법은 크게 세 가지입니다: 직접 설정(Push), 함수 바인딩(Poll), 이벤트/델리게이트 기반(Event-Driven).
함수 바인딩 (Poll)
매 프레임 바인딩 함수를 호출하여 값을 폴링합니다. 에디터에서 설정이 간편하지만 성능에 악영향을 줍니다. 값이 변하지 않아도 매 프레임 함수가 호출됩니다.
이벤트 기반 (Push)
데이터 변경 시에만 위젯을 업데이트합니다. 델리게이트/이벤트 디스패처를 사용하여 필요한 시점에만 UI를 갱신합니다. 프로덕션 코드에 권장됩니다.
UMG 에디터의 "Bind" 드롭다운으로 설정하는 함수 바인딩은 매 프레임 호출됩니다. 위젯이 100개이고 각각 2개의 바인딩이 있다면 매 프레임 200회 함수 호출이 발생합니다. 프로토타이핑에는 편리하지만, 실제 게임에서는 이벤트 기반 업데이트를 사용하세요.
C++ 이벤트 기반 바인딩
델리게이트와 이벤트 디스패처를 활용한 효율적 업데이트
// 데이터 소스 (캐릭터 또는 게임 시스템)
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(
FOnHealthChanged, float, CurrentHP, float, MaxHP);
UCLASS()
class UHealthComponent : public UActorComponent
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintAssignable)
FOnHealthChanged OnHealthChanged;
void SetHealth(float NewHealth)
{
CurrentHealth = FMath::Clamp(NewHealth, 0.f, MaxHealth);
// 변경 시에만 브로드캐스트
OnHealthChanged.Broadcast(CurrentHealth, MaxHealth);
}
private:
float CurrentHealth = 100.f;
float MaxHealth = 100.f;
};
// UI 위젯 (소비자)
UCLASS()
class UHealthBarWidget : public UUserWidget
{
GENERATED_BODY()
protected:
UPROPERTY(meta = (BindWidget))
UProgressBar* HealthBar;
virtual void NativeConstruct() override
{
Super::NativeConstruct();
// 이벤트 구독 - HP 변경 시에만 업데이트
if (auto* HC = GetOwningPlayerPawn()->FindComponentByClass<UHealthComponent>())
{
HC->OnHealthChanged.AddDynamic(this, &UHealthBarWidget::HandleHealthChanged);
}
}
UFUNCTION()
void HandleHealthChanged(float Current, float Max)
{
HealthBar->SetPercent(Max > 0.f ? Current / Max : 0.f);
}
};
다중 속성 동기화 패턴
여러 데이터를 한 번에 UI에 반영하는 구조
// UI에 필요한 데이터를 구조체로 묶기
USTRUCT(BlueprintType)
struct FPlayerHUDData
{
GENERATED_BODY()
UPROPERTY() float HealthPercent = 1.f;
UPROPERTY() float ManaPercent = 1.f;
UPROPERTY() int32 Level = 1;
UPROPERTY() FText PlayerName;
UPROPERTY() float ExpPercent = 0.f;
};
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(
FOnHUDDataChanged, const FPlayerHUDData&, Data);
// HUD 위젯에서 구조체 전체를 받아 업데이트
void UPlayerHUD::OnHUDDataUpdated(const FPlayerHUDData& Data)
{
HealthBar->SetPercent(Data.HealthPercent);
ManaBar->SetPercent(Data.ManaPercent);
LevelText->SetText(FText::AsNumber(Data.Level));
NameText->SetText(Data.PlayerName);
ExpBar->SetPercent(Data.ExpPercent);
}
여러 속성을 개별 델리게이트로 관리하면 코드가 복잡해집니다. 관련 데이터를 구조체로 묶어 한 번의 이벤트로 전달하면 코드가 단순해지고, UI 업데이트 시점이 일관됩니다. 이 패턴은 MVVM의 ViewModel 개념으로 자연스럽게 확장됩니다.
바인딩 패턴 비교
각 바인딩 방식의 장단점과 적합한 사용 시나리오
| 바인딩 방식 | 업데이트 주기 | 성능 | 적합한 용도 |
|---|---|---|---|
| 함수 바인딩 (Poll) | 매 프레임 | 낮음 | 프로토타이핑, 항상 변하는 값 |
| 직접 Set 호출 | 수동 | 높음 | 단순한 1회성 업데이트 |
| 델리게이트/이벤트 | 변경 시 | 높음 | 대부분의 프로덕션 코드 |
| MVVM ViewModel | 변경 시 | 높음 | 복잡한 UI, 분리된 아키텍처 |
핵심 요약
- UMG의 함수 바인딩(에디터 Bind 드롭다운)은 매 프레임 폴링하므로 프로덕션에서는 사용을 자제해야 합니다
- 이벤트/델리게이트 기반 업데이트가 가장 효율적이며, 데이터 변경 시에만 UI를 갱신합니다
- 관련 데이터를 구조체로 묶어 한 번의 이벤트로 전달하면 코드 단순성과 업데이트 일관성이 향상됩니다
DECLARE_DYNAMIC_MULTICAST_DELEGATE로 블루프린트에서도 바인딩 가능한 이벤트를 정의합니다- 이 패턴은 다음 강의에서 다룰 MVVM 아키텍처의 기초가 됩니다
도전 과제
배운 내용을 직접 실습해보세요
Widget Blueprint에서 TextBlock의 Text 속성에 함수 바인딩을 설정하여 플레이어의 HP, 이름, 점수를 실시간 표시하세요. GetText_ 함수 패턴과 바인딩 드롭다운 사용법을 익힙니다.
Tick 기반 폴링 바인딩 대신, 델리게이트를 사용한 이벤트 기반 업데이트를 구현하세요. 플레이어 HP 변경 시에만 UI가 업데이트되도록 OnHealthChanged 델리게이트를 만들고 바인딩합니다.
동일한 UI를 (1) Tick 폴링, (2) 함수 바인딩, (3) 이벤트 기반 세 가지 방식으로 구현하고, stat slate와 프로파일링 도구로 각 방식의 CPU 비용을 비교 분석하는 벤치마크를 수행하세요.