AttributeSet:属性的栖息地
结构
属性不是散落在各处的变量,全部放在一个 UAttributeSet 子类里:
UCLASS()
class UMyAttributeSet : public UAttributeSet
{
GENERATED_BODY()
public:
// 生命
UPROPERTY(BlueprintReadOnly, Category="Health")
FGameplayAttributeData Health;
UPROPERTY(BlueprintReadOnly, Category="Health")
FGameplayAttributeData MaxHealth;
// 法力
UPROPERTY(BlueprintReadOnly, Category="Mana")
FGameplayAttributeData Mana;
UPROPERTY(BlueprintReadOnly, Category="Mana")
FGameplayAttributeData MaxMana;
};
每个 FGameplayAttributeData 内部有 BaseValue(基础值,决定"上限一类")与 CurrentValue(当前值,决定"此刻多少")。
初始化:三种做法
| 做法 | 适合 | 说明 |
|---|---|---|
| 构造函数直接 SetBaseValue | 固定初始属性 | 简单,部分场景不权威 |
| 效果初始化(用一个"初始化 GE") | 推荐,数值可配 | 配一个 Instant GE 设基础值 |
| 数据表(DataTable)驱动 | 属性随等级/职业变化 | GE 从表格读值 |
推荐做法:配一个 GE_InitStats(Instant GE),Modifiers 里把 MaxHealth 等设为需要的基础值,角色 BeginPlay 时应用一次。
为什么这样比构造函数直接写好?——因为"100 级时 MaxHealth 多少"这类数值应当走配置资产,而不是硬编码在 C++ 里(第 1 本提到的"数据配置化"原则在 GAS 里的体现)。
在 C++ 里取属性
const UMyAttributeSet* Set = ASC->GetSet<UMyAttributeSet>();
float Cur = Set->GetHealth();
float Max = Set->GetMaxHealth();
蓝图里可直接 Get Health / Get MaxHealth(AttributeSet 的变量默认 BlueprintReadOnly——建议只读,写只走 GE)。
属性变化通知(UI 绑定的基础)
AttributeSet 有 PreAttributeChange / PostGameplayEffectExecute 两个回调:
void UMyAttributeSet::PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data)
{
Super::PostGameplayEffectExecute(Data);
if (Data.EvaluatedData.Attribute == GetHealthAttribute())
{
// 通知 UI、拼受击飘字
OnHealthChanged.Broadcast(GetHealth());
}
}
GAS 官方推荐把 UI 通知放在 AttributeSet 里——它是所有 GE 的公共下游。
本章小结
- 属性集中放 AttributeSet,每个属性 = BaseValue(基础)+ CurrentValue(当前)。
- 初始化推荐"初始化 GE",数值走配置资产。
- UI 监听走 AttributeSet 的
PostGameplayEffectExecute回调。
