UI와 C++ 연결
19강. UI와 C++ 연결
1. 이번 강의에서 해결할 문제
Widget이 매 프레임 플레이어와 점수를 검색해 텍스트를 갱신합니다. C++가 상태 변경을 알리고 Widget Blueprint는 화면 표현만 담당하도록 바꿉니다.
2. 학습 목표
3. 핵심 개념
UMG Widget은 로컬 화면 표현이므로 PlayerController가 생성·보관하기 좋습니다. HealthComponent와 Subsystem은 Widget을 직접 include하지 않습니다. Controller가 둘 사이를 연결하는 조정자 역할을 합니다.
초기 이벤트는 Widget 바인딩 전에 발생할 수 있습니다. 따라서 Widget 생성 후 Getter로 현재값을 한 번 표시하고 이후 Delegate 이벤트로 갱신합니다.
4. 단계별 실습
파일 경로: Source/TopDownSurvival/UI/SurvivalHUDWidget.h
#pragma once
#include "CoreMinimal.h"
#include "Blueprint/UserWidget.h"
#include "SurvivalHUDWidget.generated.h"
UCLASS(Abstract)
class TOPDOWNSURVIVAL_API USurvivalHUDWidget : public UUserWidget
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintImplementableEvent, Category = "HUD")
void UpdateHealth(float CurrentHealth, float MaxHealth);
UFUNCTION(BlueprintImplementableEvent, Category = "HUD")
void UpdateScore(int32 Score);
UFUNCTION(BlueprintImplementableEvent, Category = "HUD")
void ShowGameOver();
};
파일 경로: Source/TopDownSurvival/Player/SurvivalPlayerController.h · 추가
class USurvivalHUDWidget;
UPROPERTY(EditDefaultsOnly, Category = "UI")
TSubclassOf<USurvivalHUDWidget> HUDWidgetClass;
UPROPERTY()
TObjectPtr<USurvivalHUDWidget> HUDWidget;
UFUNCTION()
void HandleHealthChanged(float CurrentHealth, float MaxHealth);
UFUNCTION()
void HandleScoreChanged(int32 Score);
UFUNCTION()
void HandleGameOver();
파일 경로: Source/TopDownSurvival/Player/SurvivalPlayerController.cpp · BeginPlay 추가
#include "Components/SurvivalHealthComponent.h"
#include "Systems/SurvivalGameSubsystem.h"
#include "UI/SurvivalHUDWidget.h"
if (HUDWidgetClass)
{
HUDWidget = CreateWidget<USurvivalHUDWidget>(this, HUDWidgetClass);
if (HUDWidget)
{
HUDWidget->AddToViewport();
}
}
USurvivalGameSubsystem* Game =
GetGameInstance()->GetSubsystem<USurvivalGameSubsystem>();
ASurvivalCharacter* Character = Cast<ASurvivalCharacter>(GetPawn());
if (Game && HUDWidget)
{
Game->OnScoreChanged.AddDynamic(this, &ThisClass::HandleScoreChanged);
Game->OnGameOver.AddDynamic(this, &ThisClass::HandleGameOver);
HUDWidget->UpdateScore(Game->GetScore());
}
if (Character && Character->GetHealthComponent() && HUDWidget)
{
USurvivalHealthComponent* Health = Character->GetHealthComponent();
Health->OnHealthChanged.AddDynamic(this, &ThisClass::HandleHealthChanged);
HUDWidget->UpdateHealth(Health->GetCurrentHealth(), Health->GetMaxHealth());
}
void ASurvivalPlayerController::HandleHealthChanged(float Current, float Max)
{
if (HUDWidget) HUDWidget->UpdateHealth(Current, Max);
}
void ASurvivalPlayerController::HandleScoreChanged(int32 Score)
{
if (HUDWidget) HUDWidget->UpdateScore(Score);
}
void ASurvivalPlayerController::HandleGameOver()
{
if (HUDWidget) HUDWidget->ShowGameOver();
SetIgnoreMoveInput(true);
}
Character에 const가 아닌 GetHealthComponent Getter를 public으로 추가합니다.
Widget Blueprint
WBP_SurvivalHUD를 USurvivalHUDWidget 자식으로 만들고 Progress Bar, Score Text, 숨겨진 Game Over Panel을 배치합니다. 세 BlueprintImplementableEvent에서 표시만 변경합니다.
5. 코드가 동작하는 이유
Controller는 자신의 로컬 Widget과 Possess한 Character에 접근할 수 있어 연결 지점이 됩니다. 상태 소유자는 Delegate만 Broadcast하고 Widget은 C++ 부모 이벤트를 구현해 표현합니다. Getter 초기화가 바인딩 이전 이벤트 누락을 보완합니다.
6. 자주 하는 실수와 해결법
7. 직접 실습
8. 이해 점검 질문 3개
9. 핵심 요약
UI와 C++ 연결 미니 퀴즈
선택 즉시 정답과 해설을 확인할 수 있습니다. 결과는 이 브라우저에만 저장됩니다.
학습을 마쳤나요?
직접 실습과 점검 질문까지 확인한 뒤 완료로 표시하세요.