๐ ์ ๋ฐ๋ฏธ GAS ๊ฐ์ ์ค ๊ธฐ๋กํด๋๊ณ ์ถ์ ๋ด์ฉ์ ์ ์ด๋ ํฌ์คํธ
Section 4 : UI ๊ตฌํ (MVC ํจํด)

View : ๊ฐ WBP
WidgetController : WidgetController ํด๋์ค
Model : Data๋ค
View -> Controller -> Model ์ ์ผ๋ฐฉํฅ์ ์ข
์์ฑ์ ์ง๋๋๋ก ํ๋ค.
(Model์ Controller์ ์์ธ๋ฅผ ๋ชจ๋ฅด๊ณ , Controller๋ ๋ง์ฐฌ๊ฐ์ง๋ก ๊ฐ Widget์ผ๋ก๋ถํฐ ๋
๋ฆฝ์ )
UAuraUserWidget
public:
// ์์ ฏ ๋ธ๋ฃจํ๋ฆฐํธ์์ ์ปจํธ๋กค๋ฌ ์
ํ ์ ์๋๋ก
UFUNCTION(BlueprintCallable)
void SetWidgetController(UObject* InWidgetController);
// ์ผ๋ฐฉํฅ ์ข
์์ฑ์ ์ํด ์์ ฏ์ด ์ปจํธ๋กค๋ฌ๋ฅผ ํฌ์ธํฐ๋ก ๋ค๊ณ ์ปจํธ๋กค๋ฌ๋ ์์ ฏ ์ ๋ค๊ณ ์์
UPROPERTY(BlueprintReadOnly)
TObjectPtr<UObject> WidgetController;
protected:
// ์ปจํธ๋กค๋ฌ๊ฐ ์
๋๋์ง ํ์ธํ๊ธฐ์ํ ํจ์๋ก ์ผ์ข
์ BeginPlay ์ญํ ์ํ
UFUNCTION(BlueprintImplementableEvent)
void WidgetControllerSet();
void UAuraUserWidget::SetWidgetController(UObject* InWidgetController)
{
WidgetController = InWidgetController;
// ๋ธ๋ฃจํ๋ฆฐํธ ์ด๋ฒคํธ ํธ์ถ
WidgetControllerSet();
}
๋ธ๋ฃจํ๋ฆฐํธ์์ ์ฌ์ฉ ์์

UAuraWidgetController
UObject ํด๋์ค๋ฅผ ์์๋ฐ์๋ค.
public:
// FWidgetControllerParams๋ 4๊ฐ์ ๋ฉค๋ฒ๋ฅผ ๋ฌถ์ด๋์ ๊ตฌ์กฐ์ฒด์
UFUNCTION(BlueprintCallable)
void SetWidgetControllerParams(const FWidgetControllerParams& WCParams);
protected:
// ์์ ์ปจํธ๋กค๋ฌ๋ค์ด ์ ๊ทผํ ์ ์๋๋ก protected
// Model์ ์ ๊ทผํ๊ธฐ ์ํ ํฌ์ธํฐ๋ค (์ผ๋ฐฉํฅ ์ข
์์ฑ ์ ์ง View -> Controller -> Model)
UPROPERTY(BlueprintReadOnly, Category="WidgetController")
TObjectPtr<APlayerController> PlayerController;
UPROPERTY(BlueprintReadOnly, Category="WidgetController")
TObjectPtr<APlayerState> PlayerState;
UPROPERTY(BlueprintReadOnly, Category="WidgetController")
TObjectPtr<UAbilitySystemComponent> AbilitySystemComponent;
UPROPERTY(BlueprintReadOnly, Category="WidgetController")
TObjectPtr<UAttributeSet> AttributeSet;
์ปจํธ๋กค๋ฌ ์์ฑ๊ณผ ๋ฉค๋ฒ ํ ๋น์ ํ์ด๋ฐ์ ์ก๊ธฐ์ํด HUD ํด๋์ค๋ฅผ ํ์ฉํ๋ค.
๊ฒ์๋ชจ๋์์ HUD ํด๋์ค๋ฅผ ์ง์ ํ๊ณ ์ฌ์ฉํ๋ค.
public:
UPROPERTY()
TObjectPtr<UAuraUserWidget> OverlayWidget;
// Controller๋ ๊ฐ์ด ๋ง๋ค๊ธฐ (Getter์ง๋ง ์๋ค๋ฉด ํ๋ ๋ง๋ค๊ณ ์ด๋ฏธ ์๋ค๋ฉด ์๋ ์ปจํธ๋กค๋ฌ ๋ฆฌํด)
UOverlayWidgetController* GetOverlayWidgetController(const FWidgetControllerParams& WCParams);
// Overlay ๊ตฌ์ฑ์ ์ํ ์์ ฏ๊ณผ ์ปจํธ๋กค๋ฌ ์์ฑ
void InitOverlay(APlayerController* PC, APlayerState* PS, UAbilitySystemComponent* ASC, UAttributeSet* AS);
private:
UPROPERTY(EditAnywhere)
TSubclassOf<UAuraUserWidget> OverlayWidgetClass;
// ์ปจํธ๋กค๋ฌ ๋ง๋ค๊ธฐ ์ํ ํด๋์ค์ ๋ง๋ ๋ค์ ํฌ์ธํฐ
UPROPERTY(EditAnywhere)
TSubclassOf<UOverlayWidgetController> OverlayWidgetControllerClass;
UPROPERTY()
TObjectPtr<UOverlayWidgetController> OverlayWidgetController;
InitOverlay() ํจ์์์ ์์ ฏ ์์ฑ๊ณผ ์ปจํธ๋กค๋ฌ ํ ๋น
UOverlayWidgetController* AAuraHUD::GetOverlayWidgetController(const FWidgetControllerParams& WCParams)
{
if (OverlayWidgetController == nullptr)
{
OverlayWidgetController = NewObject<UOverlayWidgetController>(this,OverlayWidgetControllerClass);
OverlayWidgetController->SetWidgetControllerParams(WCParams);
}
return OverlayWidgetController;
}
void AAuraHUD::InitOverlay(APlayerController* PC, APlayerState* PS, UAbilitySystemComponent* ASC, UAttributeSet* AS)
{
// ๋จ์ check - crash ๋ณด๋ค ์์ธํ๊ฒ ๋ฉ์์ง ์ ๋ฌ
checkf(OverlayWidgetClass, TEXT("OverlaywidgetClass Uninitialized, Check BP_AuraHUD"));
checkf(OverlayWidgetControllerClass, TEXT("OverlayWidgetControllerClass Uninitialized, Check BP_AuraHUD"));
UUserWidget* Widget = CreateWidget<UUserWidget>(GetWorld(),OverlayWidgetClass);
OverlayWidget = Cast<UAuraUserWidget>(Widget);
const FWidgetControllerParams WCParams(PC,PS,ASC,AS);
OverlayWidgetController = GetOverlayWidgetController(WCParams);
OverlayWidget->SetWidgetController(OverlayWidgetController);
Widget->AddToViewport();
}
InitOverlay()์ ํธ์ถ์ AAuraCharacter::InitAbilityActorInfo()์์
PlayerController๋ฅผ ํตํด HUD์ ์ ๊ทผํ ์ ์๋ค.void AAuraCharacter::InitAbilityActorInfo()
{
AbilitySystemComponent = AuraPlayerState->GetAbilitySystemComponent();
AbilitySystemComponent->InitAbilityActorInfo(AuraPlayerState, this);
AttributeSet = AuraPlayerState->GetAttributeSet();
// InitOverlay
// ๋ฉํฐํ๋ ์ด์ด์ ๊ฒฝ์ฐ ํ๋ ์ด์ด๋ธ ์บ๋ฆญํฐ๊ฐ ํญ์ Playercontroller๋ฅผ ๋ค๊ณ ์์ง๋ ์๊ธฐ๋๋ฌธ์ ValidCheck์ ํ๊ณ ๋์ด๊ฐ๋ฉด
// ๋ค๋ฅธ ํด๋ผ์ด์ธํธ๊ฐ ์ปจํธ๋กค ์ค์ธ ํ๋ ์ด์ด ์บ๋ฆญํฐ์์ ASSERT๊ฐ ๋ฐ์ํ ์ ์๊ธฐ๋๋ฌธ์ if()๋ก valid ํ์ธ๋ ๊ฒฝ์ฐ๋ง Initํด์ฃผ๋ฉด ๋จ
if (APlayerController* PlayerController = GetController<APlayerController>())
{
// check(PlayerController) X , ๋ง์ฐฌ๊ฐ์ง๋ก HUD๋ 1 ํ๋ ์ด์ดํํ
๋ง ์์ผ๋๊น if() ์ฒดํฌ๋ง ํ๊ธฐ
if (AAuraHUD* AuraHUD = PlayerController->GetHUD<AAuraHUD>())
{
AuraHUD->InitOverlay(PlayerController,AuraPlayerState,AbilitySystemComponent,AttributeSet);
}
}
}
์ปจํธ๋กค๋ฌ์์ ์ํ
OverlayWidgetController.h
// Dynamic : BP(ํนํ WBP)์ ์ฌ์ฉํ ๊ฒ์ด๋ฏ๋ก
// Multicast : ์ฌ๋ฌ Widget์ ์ฐ๊ฒฐํ ์์ ์ด๋ฏ๋ก
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnHealthChangedSignature,float,NewHealth);
// BluprintAssignable : Multicast์ ์ฌ์ฉ, ๋ธ๋ฃจํ๋ฆฐํธ์์ ๋ธ๋ฆฌ๊ฒ์ดํธ๊ฐ ๋
ธ์ถ๋๋๋ก
UPROPERTY(BlueprintAssignable, Category="GAS|Attributes")
FOnHealthChangedSignature OnHealthChanged;
// ์ฝ๋ฐฑ ํจ์๋ค ๋ง๋ค๊ธฐ
// ASC์์ ์ ๊ณตํ๋ ๋ธ๋ฆฌ๊ฒ์ดํธ ์ฌ์ฉํ๋ฏ๋ก ์์ ๋ง์ถ๊ธฐ (const FOnAttributeChangeData&)
void HealthChanged(const FOnAttributeChangeData& Data) const;
OverlayWidgetController.cpp
void UOverlayWidgetController::BroadcastInitialValues()
{
// AttributeSet ๋ฉค๋ฒ๊ฐ ํ์คํ ํ ๋น๋ ์ดํ์ ๋ธ๋ก๋์บ์คํ
๋๋ค๋ ๊ฒ์ ์ ์ ๋ก ํ๋ฏ๋ก CastChecked ์ฌ์ฉ
UAuraAttributeSet* AuraAttributeSet = CastChecked<UAuraAttributeSet>(AttributeSet);
OnHealthChanged.Broadcast(AuraAttributeSet->GetHealth());
}
void UOverlayWidgetController::BindCallbacksToDependencies()
{
UAuraAttributeSet* AuraAttributeSet = CastChecked<UAuraAttributeSet>(AttributeSet);
// ASC์ ๋ธ๋ฆฌ๊ฒ์ดํธ ๋ฐ์์ค๊ธฐ, Dynamic ๋ธ๋ฆฌ๊ฒ์ดํธ๊ฐ ์๋๋ฏ๋ก AddUObject๋ก ๋ฐ์ธ๋ฉ
// ๋ฐ์ธ๋ฉํ ์ดํธ๋ฆฌ๋ทฐํธ ๊ตฌ์กฐ์ฒด๋ฅผ ์ธ์๋ก ๋ฃ๊ธฐ
AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(
AuraAttributeSet->GetHealthAttribute()) // ๋ธ๋ฆฌ๊ฒ์ดํธ ๋ถ๋ฌ์ค๊ณ
.AddUObject(this,&UOverlayWidgetController::HealthChanged); // ๋ฐ์ธ๋ฉ (์ค๋ธ์ ํธ, ์ฝ๋ฐฑํจ์)
}
void UOverlayWidgetController::HealthChanged(const FOnAttributeChangeData& Data) const
{
OnHealthChanged.Broadcast(Data.NewValue);
}
๋ธ๋ฆฌ๊ฒ์ดํธ ํ ๋น ์์

https://github.com/jongmin7759/Unreal_GAS/commit/f8daafac54a063629bf40d2d0af01b7b7dbc74b3
https://github.com/jongmin7759/Unreal_GAS/commit/db3f63fb9566ba3d6666d7cecd2644ef1f3eecc9