Files
PHY/GAS_AttributeSystem_Notes.md
2026-03-03 01:23:02 +08:00

8.1 KiB
Raw Blame History

GAS 属性系统实现记录PHY

说明:本文记录在本项目中,为古风游戏(四维:臂力/根骨/内息/身法)搭建 GAS 属性体系、派生属性、职业初始化、以及服务器端定时回复(回血/回内)等功能的实现过程。

本项目模块不对外暴露,因此代码全部放在 Source/PHY/PrivateAttributeSet/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 初始化 GASOwner=PlayerStateAvatar=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_MaxHealthMaxHealth = 100 + Constitution * 25
  • UPHY_MMC_MoveSpeedMoveSpeed = 600 + Agility * 2
  • UPHY_MMC_PhysicalAttackPhysicalAttack = 10 + Strength * 2
  • UPHY_MMC_PhysicalDefensePhysicalDefense = 5 + Constitution * 1.5

二级属性派生(示例系数,后续建议数据化)

  • UPHY_MMC_MaxInnerPowerMaxInnerPower = 100 + InnerBreath * 20
  • UPHY_MMC_TenacityTenacity = InnerBreath * 1
  • UPHY_MMC_CritChanceCritChance = 0.05 + Agility * 0.002 (clamp 0..1)
  • UPHY_MMC_CritDamageCritDamage = 1.5 + Strength * 0.005 (>=1)
  • UPHY_MMC_DodgeChanceDodgeChance = 0.02 + Agility * 0.002
  • UPHY_MMC_HitChanceHitChance = 0.9 + Agility * 0.001
  • UPHY_MMC_ParryChanceParryChance = 0.03 + Strength * 0.001
  • UPHY_MMC_CounterChanceCounterChance = 0.1 + Agility * 0.001
  • UPHY_MMC_DamageReductionDamageReduction = Constitution * 0.001
  • UPHY_MMC_HealthRegenRateHealthRegenRate = Constitution * 0.1
  • UPHY_MMC_InnerPowerRegenRateInnerPowerRegenRate = InnerBreath * 0.15

注:部分属性如穿甲/吸血更适合由装备/功法 GE 直接加成,而非完全从四维硬算。


4. GameplayEffect初始化 + 派生)

4.1 初始化四维:UPHYGE_InitPrimary

  • 文件:Source/PHY/Private/AbilitySystem/Effects/PHYGE_InitPrimary.h/.cpp
  • 类型Instant
  • SetByCaller 写入四维(复用同一个 GE 支持所有职业)

SetByCaller TagNativeGameplayTags 管理):

  • 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 每跳 GEUPHYGE_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_RegenTickSetByCaller 写入本次增量)

后续可拓展:脱战回复/坐下打坐/战斗中禁回等,均通过 GameplayTag 或状态判断来控制 RegenTick() 是否执行。


8. 代码风格/工程注意事项

8.1 UTF-8 BOM 引发的编译/IDE 问题

过程中多次遇到文件头 BOM 导致的解析错误(如 无法解析符号 '')。 已对相关文件移除 BOM例如 PlayerState / PlayerCharacter / GameInstance 等)。


9. 下一步建议(可选)

  • 将二级属性派生系数数据化DataAsset/CurveTable减少硬编码常量。
  • 装备/功法:用 GE 直接对二级属性加成(穿甲/吸血等更适合走装备词条)。
  • 战斗结算库:统一命中/闪避/招架/反击触发顺序与公式。
  • Regen 增加“脱战 N 秒后生效”等状态控制GameplayTag 驱动)。