When the base value of an attribute changes, there is UAttributeSet::PostGameplayEffectExecute()
available to access the (new) value and GameplayEffect with its context. I'm using this to print the changed value to UI (this is also done in ActionRPG).
Is there something similar available for the current value of an attribute? How to notify UI, when FGameplayAttributeData::CurrentValue
is updated?
UAttributeSet::PreAttributeChange()
is called on every value update, it doesn't provide any context so it is not possible to access the UI from there (events broadcasted by FAggregator
also don't fit).FGameplayAttributeData::CurrentValue
within the UI (the cue is triggered by the GameplayEffect who sets the current value). This is possible by deriving from a GameplayCueNotifyActor
and use its events OnExecute
and OnRemove
. However, instantiating an actor just to update UI seems to be a waste of resources.The GameplayAbilitySystem has UAbilitySystemComponent::GetGameplayAttributeValueChangeDelegate()
which returns a callback of type FOnGameplayAttributeValueChange
that is triggered whenever an attribute is changed (base value or current value). This can be used to register a delegate/callback, which can be used to update the UI.
In MyCharacter.h
// Declare the type for the UI callback.
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FAttributeChange, float, AttributeValue);
UCLASS()
class MYPROJECT_API MyCharacter : public ACharacter, public IAbilitySystemInterface
{
// ...
// This callback can be used by the UI.
UPROPERTY(BlueprintAssignable, Category = "Attribute callbacks")
FAttributeChange OnManaChange;
// The callback to be registered within AbilitySystem.
void OnManaUpdated(const FOnAttributeChangeData& Data);
// Within here, the callback is registered.
void BeginPlay() override;
// ...
}
In MyCharacter.cpp
void MyCharacter::OnManaUpdated(const FOnAttributeChangeData& Data)
{
// Fire the callback. Data contains more than NewValue, in case it is needed.
OnManaChange.Broadcast(Data.NewValue);
}
void MyCharacter::BeginPlay()
{
Super::BeginPlay();
if (AbilitySystemComponent)
{
AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(MyAttributeSet::GetManaAttribute()).AddUObject(this, &MyCharacterBase::OnManaUpdated);
}
}
In MyAttributeSet.h
UCLASS()
class MYPROJECT_API MyAttributeSet : public UAttributeSet
{
// ...
UPROPERTY(BlueprintReadOnly, Category = "Mana", ReplicatedUsing=OnRep_Mana)
FGameplayAttributeData Mana;
// Add GetManaAttribute().
GAMEPLAYATTRIBUTE_PROPERTY_GETTER(URPGAttributeSet, Mana)
// ...
}
Example for updating the UI via the EventGraph of the character blueprint, which derived from MyCharacter
. UpdatedManaInUI
is the function which prints the value to the UI.
Here, UpdatedManaInUI
retrieves the value by itself. You might want to use the AttributeValue
of OnManaChange
.