이번에는 기존의 AttributeSet의 초기값을 불러와 UI를 설정하는 단계를 넘어서
Attribute가 변화하면 실제로 UI에 변화를 반영하도록 해보겠습니다.
또 기존의 체력바 UI말고도 마나 UI도 손보도록 하겠습니다.
언리얼 엔진에서는 GAS 시스템에서 Attribute가 변경되는 경우 콜백 함수를 호출할 수 있는 함수를 제공합니다.
그 함수는 GetGameplayAttributeValueChangeDelegate 로서 AbilitySystemComponent가 호출합니다.
따라서 저 함수를 설정하면 해당하는 Attribute가 변경될 때마다 콜백함수를 호출할 수 있게 됩니다.
따라서 WidgetController에 GetGameplayAttributeValueChangeDelegate 함수를 설정하도록 하겠습니다.
1) 모든 WidgetController의 부모 AuraWidgetController
각 Attrribute마다 GetGameplayAttributeValueChangeDelegate 함수를 연결해야 하므로
하나의 함수에서 모두 처리하도록 하겠습니다.
그것을 위해 먼저 부모 WidgetController인 AuraWidgetController에 함수를 생성하겠습니다.
.
.
.
/**
*
*/
UCLASS()
class AURA_API UAuraWidgetController : public UObject
{
GENERATED_BODY()
public:
.
.
.
virtual void BindCallbacksToDependencies();
protected:
.
.
.
};
.
.
.
void UAuraWidgetController::BindCallbacksToDependencies()
{
}
함수 BindCallbacksToDependencies 에서는 Attribute에 대한
GetGameplayAttributeValueChangeDelegate를 연결하는 작업을 수행합니다.
이제 OverlayWidgetController로 이동하겠습니다.
2) Overlay UI를 위한 Controller인 OverlayWidgetController
#pragma once
#include "CoreMinimal.h"
#include "UI/WidgetController/AuraWidgetController.h"
#include "AuraOverlayWidgetController.generated.h"
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnHealthChangedSignature, float, NewHealth);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnMaxHealthChangedSignature, float, NewMaxHealth);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnManaChangedSignature, float, NewMana);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnMaxManaChangedSignature, float, NewMaxMana);
struct FOnAttributeChangeData;
/**
*
*/
UCLASS(BlueprintType, Blueprintable)
class AURA_API UAuraOverlayWidgetController : public UAuraWidgetController
{
GENERATED_BODY()
public:
virtual void BroadcastInitialValues() override;
virtual void BindCallbacksToDependencies() override;
/*
* Delgate Section
*/
UPROPERTY(BlueprintAssignable, Category = "GAS|Attributes")
FOnHealthChangedSignature OnHealthChanged;
UPROPERTY(BlueprintAssignable, Category = "GAS|Attributes")
FOnMaxHealthChangedSignature OnMaxHealthChanged;
UPROPERTY(BlueprintAssignable, Category = "GAS|Attributes")
FOnManaChangedSignature OnManaChanged;
UPROPERTY(BlueprintAssignable, Category = "GAS|Attributes")
FOnMaxManaChangedSignature OnMaxManaChanged;
protected:
void HealthChanged(const FOnAttributeChangeData& Data) const;
void MaxHealthChanged(const FOnAttributeChangeData& Data) const;
void ManaChanged(const FOnAttributeChangeData& Data) const;
void MaxManaChanged(const FOnAttributeChangeData& Data) const;
};
기존의 Health, MaxHealth에 추가적으로 Mana와 MaxMana의 Delegate를 추가하였습니다.
또한 GetGameplayAttributeValueChangeDelegate 함수에 넘겨줄 콜백함수 4종을 추가하였습니다.
#include "UI/WidgetController/AuraOverlayWidgetController.h"
#include "AbilitySystem/AuraAttributeSet.h"
void UAuraOverlayWidgetController::BroadcastInitialValues()
{
const UAuraAttributeSet* AuraAttributeSet = CastChecked<UAuraAttributeSet>(AttributeSet);
OnHealthChanged.Broadcast(AuraAttributeSet->GetHealth());
OnMaxHealthChanged.Broadcast(AuraAttributeSet->GetMaxHealth());
OnManaChanged.Broadcast(AuraAttributeSet->GetMana());
OnMaxManaChanged.Broadcast(AuraAttributeSet->GetMaxMana());
}
void UAuraOverlayWidgetController::BindCallbacksToDependencies()
{
const UAuraAttributeSet* AuraAttributeSet = CastChecked<UAuraAttributeSet>(AttributeSet);
AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(AuraAttributeSet->GetHealthAttribute())
.AddUObject(this, &UAuraOverlayWidgetController::HealthChanged);
AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(AuraAttributeSet->GetMaxHealthAttribute())
.AddUObject(this, &UAuraOverlayWidgetController::MaxHealthChanged);
AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(AuraAttributeSet->GetManaAttribute())
.AddUObject(this, &UAuraOverlayWidgetController::ManaChanged);
AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(AuraAttributeSet->GetMaxManaAttribute())
.AddUObject(this, &UAuraOverlayWidgetController::MaxManaChanged);
}
void UAuraOverlayWidgetController::HealthChanged(const FOnAttributeChangeData& Data) const
{
OnHealthChanged.Broadcast(Data.NewValue);
}
void UAuraOverlayWidgetController::MaxHealthChanged(const FOnAttributeChangeData& Data) const
{
OnMaxHealthChanged.Broadcast(Data.NewValue);
}
void UAuraOverlayWidgetController::ManaChanged(const FOnAttributeChangeData& Data) const
{
OnManaChanged.Broadcast(Data.NewValue);
}
void UAuraOverlayWidgetController::MaxManaChanged(const FOnAttributeChangeData& Data) const
{
OnMaxManaChanged.Broadcast(Data.NewValue);
}
함수들을 하나씩 살펴보면 다음과 같습니다.
BroadcastInitialValues 함수에서는 Attribute의 기본값을 OverlayWidget UI에 전달합니다.
BindCallbacksToDependencies 함수가 중요한데,
AttributeSet에서 Attribute를 가져와 해당 Attribute가 갱신될 때마다 호출할 콜백 함수를 연결합니다.
아래의 Changed 시리즈의 콜백 함수들은 델리게이트에 연결된 모든 요소에 새로운 갱신값을 broadcast합니다.
이제 마지막으로 BindCallbacksToDependencies 함수를 호출하겠습니다.
3) 헤드 업 디스플레이인 AuraHUD
.
.
.
// HUD에서 OverlayWidgetController를 가져오는 함수, 이때 가져오는 OverlayWidgetController는 항상 1개를 유지함
UAuraOverlayWidgetController* AAuraHUD::GetOverlayWidgetController(const FWidgetControllerParams& WCParams)
{
if (AuraOverlayWidgetController == nullptr)
{
AuraOverlayWidgetController = NewObject<UAuraOverlayWidgetController>(this, AuraOverlayWidgetControllerClass);
AuraOverlayWidgetController->SetWidgetControllerParams(WCParams);
AuraOverlayWidgetController->BindCallbacksToDependencies();
}
return AuraOverlayWidgetController;
}
GetOverlaywidgetController 함수의 경우, OverlayWidgetController를 가져오는 함수입니다.
이때 가져오는 OverlayWidgerController에서 BindCallbacksToDependencies 함수를 호출하면
OverlayWidgetController는 Health, MaxHealth, Mana, MaxMana의 4가지 Attribute에 대해
갱신될 때마다 연결된 UI에 콜백 함수를 호출하게 됩니다.
이제 언리얼 에디터로 넘어가 실행해보겠습니다.
블루 프린트 작업은 생략하겠습니다.
실행결과는 다음과 같습니다.
Attribute가 잘 적용되고 이에 따라 UI도 잘 적용되는 것을 확인할 수 있습니다.