虚幻GAS底层原理解剖三 (GA)

文章目录


前言

现在深入分析 GAS 中 Attribute System 的底层实现原理,包括:

  1. AttributeSet 的作用和结构

  2. FGameplayAttribute 的底层机制

  3. 属性是如何被修改的

  4. 多人同步的技术原理

  5. GAS 如何保证属性安全性、灵活性与效率

一、Attribute System 架构概览

Attribute System 是 GAS 的核心基础,用于统一管理角色的数值属性(如血量、攻击力、护甲、速度等)。

核心类关系:

cpp 复制代码
UAttributeSet           // 属性集合类,定义具体属性
    ↑
FGameplayAttribute      // 属性引用结构,用于泛型操作
    ↑
UAbilitySystemComponent // 管理所有 AttributeSet + 与 GE 交互

它并不直接处理逻辑,而是 通过 ASC、GE、Tag 等统一修改和同步数值属性。

二、UAttributeSet:属性类本体

UAttributeSet 是一个继承自 UObject 的类,开发者可自定义子类,在其中定义属性字段:

cpp 复制代码
UCLASS()
class UMyAttributeSet : public UAttributeSet
{
    GENERATED_BODY()

public:
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Health", ReplicatedUsing = OnRep_Health)
    FGameplayAttributeData Health;

    UFUNCTION()
    void OnRep_Health(const FGameplayAttributeData& OldHealth);

    static FGameplayAttribute GetHealthAttribute();
};

:
每个属性都是 FGameplayAttributeData 类型

复制代码
该类型封装了 float 值,支持缓冲、同步、变动检测等   

可通过 OnRep_XXX() 实现属性同步的回调

三、FGameplayAttributeData 的作用

它是 GAS 中实际存储属性值的类型:

cpp 复制代码
struct FGameplayAttributeData
{
    float BaseValue;
    float CurrentValue;
};

:
BaseValue:基础值,不随 BUFF 等效果改变

复制代码
CurrentValue:实际数值,会受 GE 动态影响   

内建了属性变更检测与 NetDeltaSerialize 支持

🧬 四、FGameplayAttribute:属性引用包装器

为了让 GE、GA 以"泛型方式"修改属性(而不是硬编码字段名),GAS 提供了 FGameplayAttribute:

cpp 复制代码
FGameplayAttribute MyAttribute = UMyAttributeSet::GetHealthAttribute();
ASC->SetNumericAttributeBase(MyAttribute, 100.0f);

:
所属 UClass*(哪个 AttributeSet)

复制代码
属性名 FName   

C++ 成员指针

并通过反射方式获取对应的 FGameplayAttributeData& 实例。

五、属性变更流程

属性变更路径(以 GE 加血为例):

  1. GE 的 FModifierSpec 指定修改 Health
  2. GE 应用到目标 ASC → 调用 ApplyModToAttribute()
  3. 找到 AttributeSet → 定位到 FGameplayAttributeData
  4. 修改 CurrentValue → 触发 PostGameplayEffectExecute()

若是网络游戏,调用 OnRep_Health() 同步客户端

cpp 复制代码
void UAttributeSet::PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data)
{
    if (Data.Attribute == GetHealthAttribute()) {
        if (Health.GetCurrentValue() <= 0.f) {
            // 死亡逻辑
        }
    }
}

六、属性计算流程

GAS 支持多个层级的属性修改:

层级 修改函数 特性
Base SetBaseAttributeValue 基础值
Current ApplyModToAttribute 当前值
额外运算 Execution Calculation 动态伤害、暴击等

在执行 GE 时,会通过 FAggregator 系统完成对属性的加权合并运算:

cpp 复制代码
float NewValue = BaseValue
               + AdditiveModifiers
               + MultiplicativeModifiers
               + Override (if any);

这些 Modifier 都存储在 ASC 的内部结构 FAggregatorMap 中,并会在任意值变动时自动重新计算属性。

七、属性网络同步原理

GAS 的属性同步机制非常高效:

  1. 使用 NetDeltaSerialize + FGameplayAttributeData
    每个属性结构都注册了 Delta 序列化:

cpp

复制

编辑

void FGameplayAttributeData::NetSerialize(FArchive& Ar, class UPackageMap* Map, bool& bOutSuccess)

只有当属性值变动时,才会序列化发送

自动触发 OnRep_属性名() 回调

  1. GAS 会为所有 AttributeSet 注册为子对象并同步
    在 ASC 初始化时会自动注册属性集合并设置 RepNotify:

cpp

复制

编辑

ASC->AddReplicatedSubObject(AttributeSetInstance);

八、属性保护机制(只通过 GE 修改)

:
不要在游戏逻辑中直接 Health = xxx

复制代码
必须通过 ASC 和 GE 修改属性!

:
不会触发 OnRep

复制代码
不会触发 PostGameplayEffectExecute   

不参与网络同步

推荐方法:

cpp 复制代码
FGameplayEffectSpecHandle Spec = MakeOutgoingSpec(HealthRestoreGE, 1.0f, Context);
ASC->ApplyGameplayEffectSpecToSelf(*Spec.Data.Get());

九、案例:实现护甲减伤

  1. 定义两个属性:Health, Armor
  2. 创建一个 Execution Calculation 类,逻辑如下:
cpp 复制代码
float Damage = InDamage;
float Armor = 0.f;
ExecParams.AttemptCalculateCapturedAttributeMagnitude(ArmorDef, EvalParams, Armor);
Damage *= (1 - Armor * 0.01f);  // 减伤公式
  1. 设置 OutSpec.AddOutputModifier() 作用到 Health 属性上

总结

模块 作用 说明
UAttributeSet 属性定义类 包含各个 FGameplayAttributeData
FGameplayAttributeData 属性值结构 有 Base 和 Current 值,支持序列化
FGameplayAttribute 泛型引用器 可用于在运行时访问属性
ASC 执行属性修改 持有属性容器、同步、处理 GE
相关推荐
2301_780789667 小时前
跨平台适配!SDK 游戏盾兼容全终端游戏场景
java·网络·ddos
学长毕设7 小时前
基于springboot的食品仓库管理系统
java·spring boot·后端
步行cgn8 小时前
FormHttpMessageConverter 详解:Spring MVC 中表单数据的读写转换器
java·spring·mvc
龙亘川8 小时前
构建城市公共安全数字底座:亘川智城智慧安防系统全维度解读
java·大数据·开发语言·人工智能·信息可视化
金銀銅鐵8 小时前
[Java] 用 CLI 展示 EnumMap 增删键值对时的内部变化
java·源码·ai编程
秋天的怀念_David8 小时前
第二十二夜 · 数字迷雾
java·程序人生·算法
Raas1009 小时前
AI网关部署方案?从部署到上线全流程
java·开发语言·人工智能·gateway·ai网关·企业级ai网关·企业级ai产品
niucloud-admin9 小时前
NIUCLOUD PHP SAAS上门家政使用文档:城市管理
java·前端·php
霸道流氓气质10 小时前
智能客服组件:分层意图识别、RAG Advisor 与人工转接状态机的 Vue3 + Spring AI 生产级实战
java·人工智能·spring
captain37610 小时前
MyBatis操作数据库(入门2)
java·数据库·spring boot·后端·spring·mybatis