언리얼 엔진/Gameplay Ability System - Udemy

[UE5/Gameplay Ability System(GAS)] - Attribute Change

mane 2024. 2. 15. 01:51
728x90
반응형

인사말

안녕하세요. 이번 포스트에서 GAS에서 Attribute Change를 통해서 체력과 마나를 변경해 보록 하겠습니다.


WBP_Overlay

WBP_Overlay에 만들어둔 WBP_HealthGrobeWBP_ManaGlobe를 추가해 주도록 합니다.
그리고 그래프에서는 Event Widget Controller Set 을 실행시키도록 합니다.
HealthGlobe 와 ManaGlobe 의 블루프린트 그래프는 아래와 같이 구현되여 있습니다.

WBP_Overlay
WBP_Overlay
WBP_ManaGlobe
WBP_HealthGlobe

구현부(SetWidgetController)

void UAuraUserWidget::SetWidgetController(UObject* InWidgetController)
{
    WidgetController = InWidgetController;
    WidgetControllerSet();
}

OverlayWidgetController

해당 클래스에서는 체력과 마나를 AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate 를 함수에 대한 델리게이트를 바인딩하도록 하였습니다.
그래서 체력과 마나의 값이 변할 때 각각에 해당하는 델리게이트들을 Broadcast 시키도록 하였습니다.

.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);

/**
 * 
 */
UCLASS(BlueprintType, Blueprintable)
class AURA_API UOverlayWidgetController : public UAuraWidgetController
{
    GENERATED_BODY()
public:
    virtual void BroadcastInitialValues() override;
    virtual void BindCallbacksToDependencies() override;

    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;
};
void UOverlayWidgetController::BroadcastInitialValues()
{
    if(const UAuraAttributeSet* AuraAttributeSet = CastChecked<UAuraAttributeSet>(AttributeSet))
    {
        OnHealthChanged.Broadcast(AuraAttributeSet->GetHealth());
        OnMaxHealthChanged.Broadcast(AuraAttributeSet->GetMaxHealth());
        OnManaChanged.Broadcast(AuraAttributeSet->GetMana());
        OnMaxManaChanged.Broadcast(AuraAttributeSet->GetMaxMana());
    }
}

void UOverlayWidgetController::BindCallbacksToDependencies()
{
    if(const UAuraAttributeSet* AuraAttributeSet = CastChecked<UAuraAttributeSet>(AttributeSet))
    {
        AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(
            AuraAttributeSet->GetHealthAttribute()).AddUObject(this, &ThisClass::HealthChanged);

        AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(
            AuraAttributeSet->GetMaxHealthAttribute()).AddUObject(this, &ThisClass::MaxHealthChanged);

        AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(
            AuraAttributeSet->GetManaAttribute()).AddUObject(this, &ThisClass::ManaChanged);

        AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(
            AuraAttributeSet->GetMaxManaAttribute()).AddUObject(this, &ThisClass::MaxManaChanged);
    }
}

void UOverlayWidgetController::HealthChanged(const FOnAttributeChangeData& Data) const
{
    OnHealthChanged.Broadcast(Data.NewValue);
}

void UOverlayWidgetController::MaxHealthChanged(const FOnAttributeChangeData& Data) const
{
    OnMaxHealthChanged.Broadcast(Data.NewValue);
}

void UOverlayWidgetController::ManaChanged(const FOnAttributeChangeData& Data) const
{
    OnManaChanged.Broadcast(Data.NewValue);
}

void UOverlayWidgetController::MaxManaChanged(const FOnAttributeChangeData& Data) const
{
    OnMaxManaChanged.Broadcast(Data.NewValue);
}

BroadcastInitialValues() 함수는 AuraHUD 클래스 InitOverlay 에서 실행되도록 하였습니다.


Flowchart

대략 이런식이다.


Aura Effect Actor

AuraEffectActor 에 오버랩되면 체력과 마나가 변하는 코드를 작성해준다.

void AAuraEffectActor::OnOverlap(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,
    UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
    // TODO: Change this to apply a Gameplay Effect. For now, using const_cast as hack!
    if(const IAbilitySystemInterface* AbilitySystemInterface = Cast<IAbilitySystemInterface>(OtherActor))
    {
        const UAuraAttributeSet* AuraAttributeSet = Cast<UAuraAttributeSet>(AbilitySystemInterface->GetAbilitySystemComponent()->GetAttributeSet(UAuraAttributeSet::StaticClass()));

        UAuraAttributeSet* MutableAuraAttributeSet = const_cast<UAuraAttributeSet*>(AuraAttributeSet);
        MutableAuraAttributeSet->SetHealth(AuraAttributeSet->GetHealth() + 25.f);
        MutableAuraAttributeSet->SetMana(AuraAttributeSet->GetMana() - 25.f);
        Destroy();
    }
}

결과물

AuraEffectActor(포션)을 먹으면 체력과 마나가 바뀌는 모습을 볼 수 있다.

728x90
반응형