8.1 KiB
8.1 KiB
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* AbilitySystemComponentUPHYAttributeSet* 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 = MaxHealthInnerPower = MaxInnerPower
- Apply
相关文件:
Source/PHY/Private/Character/PHYPlayerCharacter.h/.cpp
2. AttributeSet(全部在 Private)
2.1 AttributeSet 位置
Source/PHY/Private/AbilitySystem/Attributes/PHYAttributeSet.hSource/PHY/Private/AbilitySystem/Attributes/PHYAttributeSet.cpp
2.2 属性分组
Primary(基础四维)
StrengthConstitutionInnerBreathAgility
Vitals(生命)
HealthMaxHealth
Resource(资源)
InnerPowerMaxInnerPower
Derived(示例派生)
MoveSpeedPhysicalAttackPhysicalDefense
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/InnerPowerclamp 到[0, Max]- 概率类 clamp 到
[0, 1] CritDamageclamp>= 1
PostGameplayEffectExecute:- 对关键属性再兜底 clamp
- 完整实现:
OnRep_XXXGetLifetimeReplicatedProps+DOREPLIFETIME_CONDITION_NOTIFY
3. 派生属性计算(MMC)
3.1 MMC 放置位置
Source/PHY/Private/AbilitySystem/MMC/
3.2 已实现的 MMC(示例)
基础派生
UPHY_MMC_MaxHealth:MaxHealth = 100 + Constitution * 25UPHY_MMC_MoveSpeed:MoveSpeed = 600 + Agility * 2UPHY_MMC_PhysicalAttack:PhysicalAttack = 10 + Strength * 2UPHY_MMC_PhysicalDefense:PhysicalDefense = 5 + Constitution * 1.5
二级属性派生(示例系数,后续建议数据化)
UPHY_MMC_MaxInnerPower:MaxInnerPower = 100 + InnerBreath * 20UPHY_MMC_Tenacity:Tenacity = InnerBreath * 1UPHY_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.002UPHY_MMC_HitChance:HitChance = 0.9 + Agility * 0.001UPHY_MMC_ParryChance:ParryChance = 0.03 + Strength * 0.001UPHY_MMC_CounterChance:CounterChance = 0.1 + Agility * 0.001UPHY_MMC_DamageReduction:DamageReduction = Constitution * 0.001UPHY_MMC_HealthRegenRate:HealthRegenRate = Constitution * 0.1UPHY_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.StrengthData.Init.Primary.ConstitutionData.Init.Primary.InnerBreathData.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.hUPHYClassDefaults:FallbackPrimaryClasses[]:每个职业对应一套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 * RegenIntervalInnerPowerDelta = 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 驱动)。