Let's talk

RSAsyncWatchAttribute.h

Source/RSGasHelpers/Public/RSAsyncWatchAttribute.h Raw Download ZIP

Click a line number to link it. Shift-click to select a range.

1// Copyright (c) 2026 Reignance Studios. MIT License, see LICENSE.
2
3#pragma once
4
5#include "CoreMinimal.h"
6#include "Engine/CancellableAsyncAction.h"
7#include "AttributeSet.h"
8#include "GameplayEffectTypes.h"
9#include "RSAsyncWatchAttribute.generated.h"
10
11class UAbilitySystemComponent;
12
13DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FRSAttributeChanged, FGameplayAttribute, Attribute, float, NewValue, float, OldValue);
14
15/**
16 * Watches one or more attributes and fires OnChanged when any of them changes.
17 * Fires once right away with the current value, so a widget can bind in
18 * Construct and never poll in Tick. Works on clients: attribute replication
19 * runs the same change delegate.
20 *
21 * Call Cancel (or let the widget's Destruct call it) to unbind.
22 */
23UCLASS(meta = (ExposedAsyncProxy = "AsyncTask"))
24class RSGASHELPERS_API URSAsyncWatchAttribute : public UCancellableAsyncAction
25{
26 GENERATED_BODY()
27
28public:
29 UPROPERTY(BlueprintAssignable)
30 FRSAttributeChanged OnChanged;
31
32 /** Watch attributes on the actor's ASC (PlayerState setups included). */
33 UFUNCTION(BlueprintCallable, Category = "RS|GAS", meta = (BlueprintInternalUseOnly = "true", DefaultToSelf = "Actor"))
34 static URSAsyncWatchAttribute* WatchAttributes(AActor* Actor, const TArray<FGameplayAttribute>& Attributes, bool bFireInitialValue = true);
35
36 virtual void Activate() override;
37 virtual void Cancel() override;
38
39private:
40 void HandleChange(const FOnAttributeChangeData& Data);
41
42 TWeakObjectPtr<UAbilitySystemComponent> WeakASC;
43 TArray<FGameplayAttribute> Watched;
44 TArray<TPair<FGameplayAttribute, FDelegateHandle>> Bindings;
45 bool bFireInitial = true;
46};

Still desyncing in packaged builds?

Free code fixes one symptom. A Diagnostic finds the cause across your project in two days.