第一次提交

This commit is contained in:
不明不惑
2026-03-03 01:23:02 +08:00
commit 3e434877e8
1053 changed files with 102411 additions and 0 deletions

View File

@@ -0,0 +1,254 @@
# 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 初始化 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_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 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 每跳 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 驱动)。