# GAS 属性系统实现记录(PHY) > 说明:本文记录在本项目中,为古风游戏(四维:臂力/根骨/内息/身法)搭建 GAS 属性体系、派生属性、职业初始化、以及服务器端定时回复(回血/回内)等功能的实现过程。 > > 本项目模块不对外暴露,因此代码全部放在 `Source/PHY/Private` 内(AttributeSet/GE/MMC/GameplayTags 等)。 --- ## 0. 总体目标 - 基础属性(Primary): - **Strength(臂力)** - **Constitution(根骨)** - **InnerBreath(内息)** - **Agility(身法)** - 其他属性由四维派生(MMC 计算)或由装备/功法 GE 附加。 - 不对外提供公共模块 API:代码全部在 `Private`。 --- ## 1. GAS 组件挂载位置与初始化 ### 1.1 AbilitySystemComponent 放在 PlayerState - 在 `APHYPlayerState` 的构造函数中创建: - `UAbilitySystemComponent* AbilitySystemComponent` - `UPHYAttributeSet* AttributeSet` - 设置复制: - `AbilitySystemComponent->SetIsReplicated(true)` - `AbilitySystemComponent->SetReplicationMode(EGameplayEffectReplicationMode::Minimal)`(适合 PlayerState) 相关文件: - `Source/PHY/Private/Gameplay/Player/PHYPlayerState.cpp` ### 1.2 Character 初始化 GAS:Owner=PlayerState,Avatar=Character 在 `APHYPlayerCharacter`: - `PossessedBy()`(服务器)调用 `InitializeGAS()` - `OnRep_PlayerState()`(客户端)也调用 `InitializeGAS()` 初始化逻辑(核心): - `ASC->InitAbilityActorInfo(PlayerState, this)` - 服务器: - Apply `UPHYGE_InitPrimary`(设置四维初值) - Apply `UPHYGE_DerivedAttributes`(无限期派生属性:Override + MMC) - 设置资源/当前值: - `Health = MaxHealth` - `InnerPower = MaxInnerPower` 相关文件: - `Source/PHY/Private/Character/PHYPlayerCharacter.h/.cpp` --- ## 2. AttributeSet(全部在 Private) ### 2.1 AttributeSet 位置 - `Source/PHY/Private/AbilitySystem/Attributes/PHYAttributeSet.h` - `Source/PHY/Private/AbilitySystem/Attributes/PHYAttributeSet.cpp` ### 2.2 属性分组 #### Primary(基础四维) - `Strength` - `Constitution` - `InnerBreath` - `Agility` #### Vitals(生命) - `Health` - `MaxHealth` #### Resource(资源) - `InnerPower` - `MaxInnerPower` #### Derived(示例派生) - `MoveSpeed` - `PhysicalAttack` - `PhysicalDefense` #### Secondary(二级属性) - `Tenacity`(韧性) - `CritChance`(暴击率 0~1) - `CritDamage`(暴击伤害倍率 >=1) - `DodgeChance`(闪避 0~1) - `HitChance`(命中 0~1) - `ParryChance`(招架 0~1) - `CounterChance`(反击 0~1;业务逻辑要求闪避/招架成功后再判定) - `ArmorPenetration`(穿甲 0~1;目前字段存在,数值来源更多偏装备/功法) - `DamageReduction`(免伤 0~1) - `LifeSteal`(吸血 0~1;目前字段存在,数值来源更多偏装备/功法) - `HealthRegenRate`(生命回复/秒) - `InnerPowerRegenRate`(内力回复/秒) ### 2.3 Clamp 与复制 在 AttributeSet 内实现: - `PreAttributeChange`: - `Health` / `InnerPower` clamp 到 `[0, Max]` - 概率类 clamp 到 `[0, 1]` - `CritDamage` clamp `>= 1` - `PostGameplayEffectExecute`: - 对关键属性再兜底 clamp - 完整实现: - `OnRep_XXX` - `GetLifetimeReplicatedProps` + `DOREPLIFETIME_CONDITION_NOTIFY` --- ## 3. 派生属性计算(MMC) ### 3.1 MMC 放置位置 `Source/PHY/Private/AbilitySystem/MMC/` ### 3.2 已实现的 MMC(示例) #### 基础派生 - `UPHY_MMC_MaxHealth`:`MaxHealth = 100 + Constitution * 25` - `UPHY_MMC_MoveSpeed`:`MoveSpeed = 600 + Agility * 2` - `UPHY_MMC_PhysicalAttack`:`PhysicalAttack = 10 + Strength * 2` - `UPHY_MMC_PhysicalDefense`:`PhysicalDefense = 5 + Constitution * 1.5` #### 二级属性派生(示例系数,后续建议数据化) - `UPHY_MMC_MaxInnerPower`:`MaxInnerPower = 100 + InnerBreath * 20` - `UPHY_MMC_Tenacity`:`Tenacity = InnerBreath * 1` - `UPHY_MMC_CritChance`:`CritChance = 0.05 + Agility * 0.002 (clamp 0..1)` - `UPHY_MMC_CritDamage`:`CritDamage = 1.5 + Strength * 0.005 (>=1)` - `UPHY_MMC_DodgeChance`:`DodgeChance = 0.02 + Agility * 0.002` - `UPHY_MMC_HitChance`:`HitChance = 0.9 + Agility * 0.001` - `UPHY_MMC_ParryChance`:`ParryChance = 0.03 + Strength * 0.001` - `UPHY_MMC_CounterChance`:`CounterChance = 0.1 + Agility * 0.001` - `UPHY_MMC_DamageReduction`:`DamageReduction = Constitution * 0.001` - `UPHY_MMC_HealthRegenRate`:`HealthRegenRate = Constitution * 0.1` - `UPHY_MMC_InnerPowerRegenRate`:`InnerPowerRegenRate = InnerBreath * 0.15` > 注:部分属性如穿甲/吸血更适合由装备/功法 GE 直接加成,而非完全从四维硬算。 --- ## 4. GameplayEffect(初始化 + 派生) ### 4.1 初始化四维:`UPHYGE_InitPrimary` - 文件:`Source/PHY/Private/AbilitySystem/Effects/PHYGE_InitPrimary.h/.cpp` - 类型:Instant - 用 `SetByCaller` 写入四维(复用同一个 GE 支持所有职业) SetByCaller Tag(NativeGameplayTags 管理): - `Data.Init.Primary.Strength` - `Data.Init.Primary.Constitution` - `Data.Init.Primary.InnerBreath` - `Data.Init.Primary.Agility` ### 4.2 派生属性:`UPHYGE_DerivedAttributes` - 文件:`Source/PHY/Private/AbilitySystem/Effects/PHYGE_DerivedAttributes.h/.cpp` - 类型:Infinite - Modifiers:全部使用 `Override + MMC` - 包含 `MaxHealth/MoveSpeed/PhysicalAttack/PhysicalDefense` - 包含新增二级属性/资源上限(如 `MaxInnerPower`、暴击等) --- ## 5. GameplayTags 组织(集中管理,避免硬编码 FName) ### 5.1 Init 属性 Tag - `Source/PHY/Private/GameplayTags/InitAttributeTags.h/.cpp` ### 5.2 Regen Tag - `Source/PHY/Private/GameplayTags/RegenTags.h/.cpp` ### 5.3 ini 配置 - 新增/维护:`Config/DefaultGameplayTags.ini` - 包含 `Data.Init.Primary.*` - 包含 `Data.Regen.*` --- ## 6. 职业/门派初始属性(全局配置) ### 6.1 职业枚举 - `Source/PHY/Private/AbilitySystem/PHYCharacterClass.h` ### 6.2 DataAsset:全局职业默认值表 - `Source/PHY/Private/AbilitySystem/PHYClassDefaults.h` - `UPHYClassDefaults`: - `FallbackPrimary` - `Classes[]`:每个职业对应一套 `FPHYPrimaryAttributes` ### 6.3 配置位置:GameInstance 考虑到 `ClassDefaults` 是全局数据,不应放在每个 Character 上: - `UPHYGameInstance` 增加 `ClassDefaults` 引用 - `GetClassDefaults()` 文件: - `Source/PHY/Private/Gameplay/PHYGameInstance.h/.cpp` 使用方式: - 在编辑器中的项目 GameInstance 蓝图(`DefaultEngine.ini` 指定的 `GameInstance_Default`)里配置 `ClassDefaults` 资产。 --- ## 7. 服务器端定时回复(方案 B:代码驱动) > 选择方案 B:不使用 Period GE,而使用 **服务器 Timer + Instant GE**。 ### 7.1 Regen 每跳 GE:`UPHYGE_RegenTick` - 文件:`Source/PHY/Private/AbilitySystem/Effects/PHYGE_RegenTick.h/.cpp` - 类型:Instant - 使用 SetByCaller: - `Data.Regen.Health`(加到 Health) - `Data.Regen.InnerPower`(加到 InnerPower) ### 7.2 Character 计时器逻辑 在 `APHYPlayerCharacter`: - 属性:`RegenInterval`(默认 1 秒) - 在 `InitializeGAS()` 服务器端启动 Timer: - `SetTimer(RegenTimerHandle, RegenTick, RegenInterval, true)` - `RegenTick()`: - `HealthDelta = HealthRegenRate * RegenInterval` - `InnerPowerDelta = InnerPowerRegenRate * RegenInterval` - Apply `UPHYGE_RegenTick`(SetByCaller 写入本次增量) > 后续可拓展:脱战回复/坐下打坐/战斗中禁回等,均通过 GameplayTag 或状态判断来控制 `RegenTick()` 是否执行。 --- ## 8. 代码风格/工程注意事项 ### 8.1 UTF-8 BOM 引发的编译/IDE 问题 过程中多次遇到文件头 BOM 导致的解析错误(如 `无法解析符号 ''`)。 已对相关文件移除 BOM(例如 PlayerState / PlayerCharacter / GameInstance 等)。 --- ## 9. 下一步建议(可选) - 将二级属性派生系数数据化(DataAsset/CurveTable),减少硬编码常量。 - 装备/功法:用 GE 直接对二级属性加成(穿甲/吸血等更适合走装备词条)。 - 战斗结算库:统一命中/闪避/招架/反击触发顺序与公式。 - Regen 增加“脱战 N 秒后生效”等状态控制(GameplayTag 驱动)。