Files
BlueRoseNote/RPGGameplayAbility重构文档_Sonnet.md

1010 lines
37 KiB
Markdown
Raw Normal View History

2026-05-30 22:33:48 +08:00
---
tags:
- GAS
- UE5
- 重构
- 技术文档
- RPGGameplayAbility
created: 2026-05-30
status: draft
project: MusicFighterGame
---
# RPGGameplayAbility GAS 插件重构文档
> 基于 Lyra Starter Game、GASShooter、UE5 GAS Aura 深度研究的全面重构方案
---
## 执行摘要
本文档基于对三个工业级 Unreal Engine 5 GAS 项目的深度代码研究,对现有 `RPGGameplayAbility` 插件进行全面评估,并提出系统性重构方案。
### 核心发现
| 维度 | 现状 | 目标 |
|------|------|------|
| 属性系统 | 1 个属性集 20 属性,混合三种游戏类型 | 三层属性体系,按职责拆分 |
| 输入绑定 | 枚举 `EGSAbilityInputID` 硬编码游戏动作 | GameplayTag 驱动,数据资产配置 |
| 能力激活策略 | 3 个布尔值分散控制 | 统一 `ActivationPolicy` + `ActivationGroup` 枚举 |
| 命名规范 | GS/RPG 前缀混用GASShooter 残留 | 统一 RPG 前缀,清理全部残留 |
| Tag 管理 | 分散在5个 DataTable | 集中式原生 Tag 单例 |
| UI 架构 | 直接调用 BlueprintImplementableEvent | WidgetController MVC 模式 |
| Cost 系统 | 仅蓝图层 `RPGCheckCost/RPGApplyCost` | 可扩展 `ULyraAbilityCost` 模式 |
### 优先级总结
- **P0立即修复**PURE_VIRTUAL 宏类名错误、GS 前缀残留清理
- **P1核心重构**:属性集拆分、输入系统 Tag 化、Activation Policy 引入
- **P2架构升级**WidgetController MVC、Tag Relationship Mapping、Cost 系统扩展
- **P3新功能**:连击系统、全局 Ability 分发、GamePhase 系统
---
## 一、现有插件深度分析
### 1.1 插件概述
| 字段 | 值 |
|------|-----|
| 名称 | RPGGameplayAbility |
| 版本 | 1.0 |
| 作者 | BlueRose |
| 起源 | 基于 GASShooter 示例项目改编 |
| 模块数 | 5 个(主模块 + LoadingScreen + GameplayMessage × 2 |
**依赖插件**GameplayAbilities、GameplayTagsEditor、EnhancedInput、CommonUI、ModelViewViewModel
### 1.2 模块结构
```
Source/
├── RPGGameplayAbility/ [主模块 - Runtime, PreLoadingScreen]
│ ├── Public/Abilities/ 核心 GAS 类ASC/Globals/Types/CueManager
│ ├── Public/AbilityTasks/ 10 个自定义 AbilityTask
│ ├── Public/AttributeSets/ 1 个合并属性集20 属性)
│ ├── Public/GameplayEffects/ 伤害 ExecutionCalculation
│ ├── Public/Target/ TargetType 策略 + Trace TargetActor
│ ├── Public/Interfaces/ IRPGInteractable
│ ├── Public/Actors/ ARPGActorBase/ARPGPickup/ARPGProjectile
│ ├── Public/Characters/ 6 个角色类Base + 3 游戏类型)
│ └── Public/UI/ 4 个 UI 组件
├── CommonLoadingScreen/
├── CommonStartupLoadingScreen/
├── GameplayMessageRuntime/
└── GameplayMessageNodes/
```
### 1.3 类层次结构(当前)
```
[Ability 层]
UGameplayAbility
└── URPGGameplayAbility ← 核心基类(激活策略/EffectContainer/多Mesh动画
└── URPGGA_CharacterJump ← 跳跃能力
[ASC 层]
UAbilitySystemComponent
└── URPGAbilitySystemComponent ← 多Mesh蒙太奇/RPC批处理/预测GE
[属性集层]
UAttributeSet
└── URPGAttributeSetBase ← 20 属性合并(反模式)
[计算层]
UGameplayEffectExecutionCalculation
└── URPGDamageExecutionCalc ← 护甲减伤 + 爆头 1.5x
[全局配置]
UAbilitySystemGlobals
└── URPGAbilitySystemGlobals ← 自定义 EffectContext
UGameplayCueManager
└── URPGGameplayCueManager ← 按需加载
UEngineSubsystem
└── URPGEngineSubsystem ← 启动时 InitGlobalData
[角色层]
ACharacter
└── ARPGCharacterBase ← GAS 角色基类
├── AActionRPGCharacter ← ARPG交互/复活)
├── ARPGFighterCharacter ← 格斗EnhancedInput
└── ARPGShooterCharacter ← 射击
```
### 1.4 现有功能清单
| 功能域 | 功能点 | 状态 |
|--------|--------|------|
| **核心 GAS** | ASC/Globals/EffectContext/CueManager | ✅ 完成 |
| **Ability 基类** | EffectContainerMap / 被动 / 武器绑定 / RPC 批处理 | ✅ 完成 |
| **多 Mesh 蒙太奇** | 支持一个 Avatar 上多个 SkeletalMesh 同时播放并复制 | ✅ 完成 |
| **AttributeSet** | 20 个属性(生命/法力/耐力/护盾/护甲/移速/等级/XP/金币) | ✅ 完成但粗糙 |
| **伤害计算** | ExecutionCalculation护甲减伤 + 爆头) | ✅ 完成 |
| **Target 系统** | TargetType 策略 + 线/球追踪 TargetActor + 散布系统 | ✅ 完成 |
| **AbilityTask** | 蒙太奇/目标等待/输入等待/交互扫描/延迟/移动 | ✅ 完成10 个) |
| **UI 异步工具** | 属性变化监听 / Tag 变化监听 | ✅ 完成 |
| **交互系统** | IRPGInteractablePre/Post/Cancel + 同步策略) | ✅ 完成 |
| **角色系统** | Base + 三种游戏类型子类 + 死亡/倒地 | ✅ 完成 |
| **连击/输入缓冲** | 无 | ❌ 缺失 |
| **Buff/Debuff 管理** | 无统一管理层 | ❌ 缺失 |
| **Cooldown C++ 封装** | 完全依赖蓝图配置 | ❌ 缺失 |
| **WidgetController MVC** | 直接 BlueprintImplementableEvent | ❌ 缺失 |
| **技能升级系统** | 无 | ❌ 缺失 |
### 1.5 代码质量问题(按严重性)
#### P0高优先级问题
**1. PURE_VIRTUAL 宏类名错误**
```cpp
// RPGGATA_Trace.h - 错误的代码
PURE_VIRTUAL(AGSGATA_Trace::DoTrace, ...); // ❌ 错误类名
PURE_VIRTUAL(AGSGATA_Trace::ShowDebugTrace, ...); // ❌ 错误类名
// 应该是:
PURE_VIRTUAL(ARPGGATA_Trace::DoTrace, ...); // ✅
```
**2. GASShooter 原始项目名残留**
- `EGSAbilityInputID`GS 前缀来自 GASShooter
- `FGSPlayMontageForMeshAndWaitForEventDelegate`
- 注释中大量 `AGSCharacterBase``GSAT_WaitTargetDataUsingActor` 引用
- 头文件注释 `#include "GASShooter/GASShooter.h"` 残留
#### P1中优先级问题
**3. 上帝属性集反模式**
`URPGAttributeSetBase` 将 20 个属性塞入单个类混合了射击游戏Armor/弹药、ARPGXP/Gold、格斗游戏Stamina的属性。职责不清难以按游戏类型裁剪。
**4. 枚举与游戏类型强耦合**
```cpp
UENUM(BlueprintType)
enum class EGSAbilityInputID : uint8 {
None,
Confirm, Cancel,
PrimaryFire, SecondaryFire, Reload, // 射击游戏专用
NextWeapon, PrevWeapon, // 武器切换
Sprint, Jump, Interact, // 通用动作
Crouch // 但对格斗游戏无意义
};
```
对于 FighterGame`PrimaryFire/Reload/NextWeapon` 等枚举完全不适用,浪费枚举空间且产生误导。
**5. 命名不一致**
| 错误 | 位置 |
|------|------|
| `EGSAbilityInputID`GS 前缀) | RPGAbilityTypes.h |
| `FAbilityMeshMontage`(无前缀) | RPGAbilitySystemComponent.h |
| `FGSPlayMontageForMeshAndWaitForEvent*`GS 前缀) | RPGAT_PlayMontageForMeshAndWaitForEvent.h |
#### P2低优先级问题
**6. 硬编码值**
```cpp
// RPGDamageExecutionCalc.cpp
const float HeadShotMultiplier = 1.5f; // 不可配置
const FName BoneName = "b_head"; // 硬编码骨骼名
// 护甲减伤公式 100/(100+Armor) 硬编码
```
**7. 死代码**
```cpp
// RPGAbilityTypes.h 中 include 但未使用
#include "Abilities/Tasks/AbilityTask_WaitGameplayEffectStackChange.h"
#include "Abilities/Tasks/AbilityTask_WaitGameplayEffectRemoved.h"
```
---
## 二、参考项目核心架构分析
### 2.1 Lyra Starter Game — 企业级 GAS 架构
Lyra 是 Epic Games 官方现代 GAS 最佳实践项目,代表了 UE5 时代的设计标准。
#### 2.1.1 Activation Policy + Activation Group 双维控制
```cpp
// LyraGameplayAbility.h
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
ELyraAbilityActivationPolicy ActivationPolicy;
// OnInputTriggered - 输入按下时激活一次
// WhileInputActive - 按住期间持续尝试激活(自动武器/冲刺)
// OnSpawn - Avatar 生成时自动激活(被动技能)
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly)
ELyraAbilityActivationGroup ActivationGroup;
// Independent - 互不干扰
// Exclusive_Replaceable - 激活时取消其他 Exclusive可被替换
// Exclusive_Blocking - 激活时取消所有 Replaceable且不可被替换
```
这两个维度分别控制"何时激活"与"激活后如何处理其他技能",相比分散的布尔值更加清晰。
#### 2.1.2 帧级输入缓冲机制
```cpp
// LyraAbilitySystemComponent.h
TArray<FGameplayAbilitySpecHandle> InputPressedSpecHandles;
TArray<FGameplayAbilitySpecHandle> InputReleasedSpecHandles;
TArray<FGameplayAbilitySpecHandle> InputHeldSpecHandles;
// ProcessAbilityInput() 每帧统一处理:
// 1. 检查 InputBlocked Tag
// 2. 收集所有待激活 AbilityHeld/Pressed
// 3. 统一 TryActivateAbility避免顺序竞争
// 4. 转发 InputReleased 事件
// 5. 清空缓存
```
避免了逐 Ability 处理时的时间顺序竞争问题。
#### 2.1.3 InputTag 三层解耦架构
```
UInputActionEnhancedInput
→ ULyraInputConfigDataAsset
→ InputTagGameplayTag
→ DynamicSpecSourceTags注入 AbilitySpec
→ ProcessAbilityInputHasTagExact 匹配激活)
```
策划可在数据层完全重组输入映射,无需修改代码。
#### 2.1.4 AbilitySet — 声明式模块化授权
```cpp
// 不可变 Data Asset包含三种授予项
UPROPERTY() TArray<FLyraAbilitySet_GameplayAbility> GrantedGameplayAbilities;
UPROPERTY() TArray<FLyraAbilitySet_GameplayEffect> GrantedGameplayEffects;
UPROPERTY() TArray<FLyraAbilitySet_AttributeSet> GrantedAttributes;
// GiveToAbilitySystem 时将 InputTag 注入 DynamicSpecSourceTags
AbilitySpec.GetDynamicSpecSourceTags().AddTag(AbilityToGrant.InputTag);
```
配合 `GameFeatureAction_AddAbilities` 实现 DLC/Mod 级别的能力热插拔。
#### 2.1.5 Tag Relationship Mapping 数据驱动
将 Ability Tag 之间的 Block/Cancel/Required 关系外部化为 Data Asset。策划修改技能互斥关系无需编译代码。
```cpp
// 激活 Ability 时动态扩展 Block/Cancel Tags
void ApplyAbilityBlockAndCancelTags(...) override {
if (TagRelationshipMapping) {
TagRelationshipMapping->GetAbilityTagsToBlockAndCancel(
AbilityTags, &ModifiedBlockTags, &ModifiedCancelTags);
}
Super::ApplyAbilityBlockAndCancelTags(...);
}
```
#### 2.1.6 Meta Attribute 管线 + HideFromModifiers
```cpp
// LyraHealthSet.h
UPROPERTY(meta=(HideFromModifiers)) FGameplayAttributeData Health; // 只有 ExecCalc 能改
UPROPERTY() FGameplayAttributeData MaxHealth;
UPROPERTY(meta=(HideFromModifiers)) FGameplayAttributeData Damage; // 临时元属性
UPROPERTY() FGameplayAttributeData Healing; // 临时元属性
// PostGameplayEffectExecute 中:
// Damage 元属性 -> 免疫检查 -> 转换为 Health 减少 -> 清零 Damage
```
`HideFromModifiers` 防止普通 GE Modifier 直接操纵 Health所有伤害必须走 ExecutionCalculation 管线。
#### 2.1.7 GlobalAbilitySystem — 全局 Ability 分发
```cpp
// WorldSubsystem管理全局 GE/Ability 分发
void RegisterASC(ULyraAbilitySystemComponent* ASC) {
// 自动将已有全局效果施加到新注册的 ASC
// 支持角色重生后自动重新应用
}
```
#### 2.1.8 AdditionalCosts 可扩展 Cost 系统
```cpp
UPROPERTY(EditDefaultsOnly, Instanced, Category=Costs)
TArray<TObjectPtr<ULyraAbilityCost>> AdditionalCosts;
// ShouldOnlyApplyCostOnHit - 远程武器未命中时不消耗弹药
```
#### 2.1.9 VerbMessage 广播模式
```cpp
// PostGameplayEffectExecute 中通过 GameplayMessageSubsystem 广播
UGameplayMessageSubsystem::BroadcastMessage(
TAG_Lyra_Damage_Message,
FLyraVerbMessage{Instigator, Target, Magnitude, Tags}
);
```
非耦合的伤害事件分发UI/音频/统计系统各自监听。
### 2.2 GASShooter — 射击类 GAS 最佳实践
#### 2.2.1 EffectContainer 系统
```cpp
// GSAbilityTypes.h - 声明式 GE 映射
TMap<FGameplayTag, FGSGameplayEffectContainer> EffectContainerMap;
// 运行时应用流程:
// MakeEffectContainerSpec(Tag) -> TargetType::GetTargets() -> MakeEffectSpec
// ApplyEffectContainerSpec(Spec) -> K2_ApplyGameplayEffectSpecToTarget
```
将技能效果配置数据驱动化,蓝图设计师无需手动编写 GE 应用代码。
#### 2.2.2 武器作为能力授予者
```cpp
// AGSWeapon 实现 IAbilitySystemInterface
// bSourceObjectMustEqualCurrentWeaponToActivate 确保武器绑定
// 卸载武器时自动 ClearAbility
```
#### 2.2.3 弹药作为独立属性集
```cpp
// GSAmmoAttributeSet.h - 独立弹药属性集
UPROPERTY() FGameplayAttributeData RifleReserveAmmo;
UPROPERTY() FGameplayAttributeData MaxRifleReserveAmmo;
// GetReserveAmmoAttributeFromTag() - Tag 到属性的动态映射
```
#### 2.2.4 PreReplication 网络优化
```cpp
// 开火时禁用弹夹复制,减少带宽消耗
DOREPLIFETIME_ACTIVE_OVERRIDE(AGSWeapon, PrimaryClipAmmo, !bIsFiring);
```
### 2.3 UE5 GAS Aura — RPG 属性与 UI 设计
#### 2.3.1 三层属性体系
```
Primary基础属性
├── Strength → Physical Damage 加成
├── Intelligence → Magical Damage / Max Mana 加成
├── Resilience → Armor / ArmorPenetration 加成
└── Vigor → Max Health 加成
↓ (通过 MMC 公式派生)
Secondary战斗属性
├── Armor ← 防御
├── ArmorPenetration← 穿透
├── BlockChance ← 格挡
├── CriticalHitChance ← 暴击率
├── CriticalHitDamage ← 暴击伤害
├── CriticalHitResistance
└── MaxHealth / MaxMana (from Vital)
↓ (最终状态)
Vital状态属性
├── Health (当前生命,不可直接修改)
└── Mana (当前法力,不可直接修改)
```
#### 2.3.2 MMC 公式化属性派生
```cpp
// MMC_MaxHealth.cpp
float UAuraMMC_MaxHealth::CalculateBaseMagnitude_Implementation(...) const {
// Capture Vigor from Target
float Vigor = ...; float PlayerLevel = CombatInterface->GetPlayerLevel();
return 80.0f + 2.5f * Vigor + 10.0f * PlayerLevel;
}
```
通过 `ICombatInterface::GetPlayerLevel()` 统一等级接口,公式参数可进一步配置为 CurveTable。
#### 2.3.3 WidgetController MVC 架构
```
AuraHUD
└── 管理 WidgetController 生命周期
├── UOverlayWidgetController ← 战斗界面(血条/法力/消息)
└── UAttributeMenuWidgetController ← 属性菜单
UAuraWidgetController基类
├── FWidgetControllerParams持有 ASC/AS/PC/PS
├── BroadcastInitialValues() ← 初始化时推送数据
└── BindCallbacksToDependencies() ← 绑定属性变化回调
// BlueprintAssignable 委托驱动 Widget 更新
UPROPERTY(BlueprintAssignable) FOnAttributeChangedSignature OnHealthChanged;
UPROPERTY(BlueprintAssignable) FOnAttributeChangedSignature OnMaxHealthChanged;
```
#### 2.3.4 声明式 EffectActor
```cpp
// AuraEffectActor.h - 策略枚举控制 GE 应用
UPROPERTY(EditAnywhere) EEffectApplicationPolicy InstantEffectApplicationPolicy;
// ApplyOnOverlap / ApplyOnEndOverlap / DoNotApply
UPROPERTY(EditAnywhere) EEffectRemovalPolicy InfiniteEffectRemovalPolicy;
// RemoveOnEndOverlap / DoNotRemove
```
无需蓝图代码即可配置药水/Buff 区域/光环。
#### 2.3.5 集中式 Tag 管理
```cpp
// AuraGameplayTags.h - 单例原生 Tag 注册
struct FAuraGameplayTags {
static const FAuraGameplayTags& Get() { return GameplayTags; }
static void InitializeNativeGameplayTags();
FGameplayTag Attributes_Primary_Strength;
FGameplayTag InputTag_LMB, InputTag_RMB;
// ...所有 Tag 单点定义
};
```
避免跨项目 Tag 名称不一致和拼写错误。
#### 2.3.6 Tag-to-Attribute 运行时映射
```cpp
// AuraAttributeSet.h
TMap<FGameplayTag, TStaticFuncPtr<FGameplayAttribute()>> m_TagsToAttributes;
// 使用:根据 Tag 动态获取属性指针O(1) 查找
// 用于 UI 属性菜单遍历所有属性
```
---
## 三、技术方案对比与借鉴决策
### 3.1 属性系统设计决策
| 方案 | 来源 | 优势 | 劣势 |
|------|------|------|------|
| 单一属性集 20 属性 | 当前 | 简单 | 上帝对象、游戏类型耦合 |
| 独立多属性集 | GASShooter | 职责清晰 | 需要 `GetAttributeSubobject` |
| **三层属性体系** | **Aura推荐** | **RPG 语义清晰、公式派生** | **初期设计工作量大** |
**决策**:采用 Aura 的三层体系思路,将现有 20 属性重组为:
- `URPGPrimaryAttributeSet`基础属性Strength/Intelligence/Vigor/Resilience
- `URPGCombatAttributeSet`战斗属性Armor/Crit/Block + Damage/Healing 元属性)
- `URPGResourceAttributeSet`资源Health/Mana/Stamina/Shield + Max/Regen
- `URPGProgressionAttributeSet`进度Level/XP/Gold可选
### 3.2 输入绑定设计决策
| 方案 | 来源 | 优势 | 劣势 |
|------|------|------|------|
| `EGSAbilityInputID` 枚举 | 当前 | 简单直接 | 游戏类型耦合、扩展困难 |
| **InputTag + DataAsset** | **Lyra推荐** | **完全解耦、数据驱动** | 需要 ProcessAbilityInput |
**决策**
1. 移除 `EGSAbilityInputID` 枚举
2. 引入 `URPGInputConfig` DataAsset`UInputAction``FGameplayTag` 映射)
3. ASC 实现 `AbilityInputTagPressed/Released/Held`
4. 实现帧级 `ProcessAbilityInput` 缓冲机制
### 3.3 UI 架构设计决策
| 方案 | 来源 | 特点 |
|------|------|------|
| BlueprintImplementableEvent | 当前 | 简单但耦合 |
| AsyncTaskAttributeChanged | 当前(工具层) | 轻量,适合简单 UI |
| **WidgetController MVC** | **Aura推荐** | **层次清晰,可测试** |
**决策**:引入 `URPGWidgetController` 基类体系,保留 `AsyncTaskAttributeChanged` 作为蓝图快速工具。
### 3.4 Cost 系统设计决策
**决策**:参考 Lyra 的 `ULyraAbilityCost` 模式,引入 `URPGAbilityCost` 抽象基类:
- `URPGAbilityCost_GameplayEffect`(标准 GE 费用)
- `URPGAbilityCost_Attribute`(直接扣属性)
- `URPGAbilityCost_TagStack`Tag 栈计数,用于弹药/特殊资源)
---
## 四、重构方案设计
### 4.1 重构目标与原则
**设计原则**
1. **向下兼容**:现有蓝图不应大规模失效,提供迁移路径
2. **游戏类型无关**:插件对 Shooter/ARPG/Fighter 均适用
3. **数据驱动**:策划可通过 DataAsset 配置,无需改代码
4. **可扩展**:新增能力类型/属性/Cost 无需修改基类
### 4.2 重构后架构总览
```
RPGGameplayAbility 插件(重构后)
├── Core/ [核心 GAS 基础设施]
│ ├── RPGAbilitySystemComponent 扩展 ASC帧级输入缓冲、ActivationGroup
│ ├── RPGAbilitySystemGlobals 全局配置(保留现有)
│ ├── RPGGameplayCueManager 按需加载(保留现有)
│ ├── RPGEngineSubsystem 启动初始化(保留现有)
│ └── RPGGameplayEffectContext 扩展 EffectContext保留现有
├── Abilities/ [能力层]
│ ├── RPGGameplayAbility 基类ActivationPolicy/Group/AdditionalCosts
│ ├── RPGAbilitySet 声明式授权 DataAsset
│ ├── RPGAbilityTagRelationshipMap Tag 互斥关系 DataAsset
│ └── RPGGlobalAbilitySystem 全局 Ability/GE 分发 WorldSubsystem
├── Attributes/ [属性层 - 三层体系]
│ ├── RPGAttributeSet 属性集基类(统一 Accessor 宏)
│ ├── RPGPrimaryAttributeSet 基础属性4个驱动派生
│ ├── RPGCombatAttributeSet 战斗属性(含 Damage/Healing 元属性)
│ └── RPGResourceAttributeSet 资源属性Health/Mana/Stamina
├── Calculations/ [计算层]
│ ├── RPGDamageExecutionCalc 扩展(支持 CritHit/Block/Penetration
│ └── RPGMMCBase MMC 基类(统一等级接口)
├── Costs/ [费用层 - 新增]
│ ├── RPGAbilityCost 抽象基类
│ ├── RPGAbilityCost_GameplayEffect GE 费用
│ └── RPGAbilityCost_TagStack Tag 栈费用(弹药)
├── Input/ [输入层 - 重构]
│ ├── RPGInputConfig DataAssetInputAction ↔ InputTag
│ └── RPGInputComponent EnhancedInputComponent 扩展
├── Tags/ [Tag 管理 - 新增]
│ └── RPGGameplayTags 集中式原生 Tag 单例
├── Target/ [目标层 - 保留]
│ ├── RPGTargetType 蓝图化目标策略
│ └── RPGGATA_Trace 追踪 TargetActor 系列
├── Tasks/ [任务层 - 保留 + 扩展]
│ └── (现有10个 Task + 新增连击Task)
├── UI/ [UI 层 - 扩展]
│ ├── RPGWidgetController WidgetController 基类(新增)
│ └── (现有 UI 组件保留)
└── Characters/ [角色层 - 整理]
├── RPGCharacterBase 基类(保留)
└── (游戏类型子类调整)
```
### 4.3 AttributeSet 拆分方案
#### 4.3.1 URPGAttributeSet新基类
```cpp
// 参考 Lyra统一 Accessor 宏 + 统一委托
#define RPG_ATTRIBUTE_ACCESSORS(ClassName, PropertyName) \
GAMEPLAYATTRIBUTE_PROPERTY_GETTER(ClassName, PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_GETTER(PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_SETTER(PropertyName) \
GAMEPLAYATTRIBUTE_VALUE_INITTER(PropertyName)
DECLARE_MULTICAST_DELEGATE_SixParams(FRPGAttributeEvent,
AActor* EffectInstigator, AActor* EffectCauser,
const FGameplayEffectSpec* EffectSpec,
float EffectMagnitude, float OldValue, float NewValue);
```
#### 4.3.2 URPGPrimaryAttributeSet
```cpp
// 4 个基础属性,驱动 Secondary 属性的 MMC 计算
FGameplayAttributeData Strength; // 力量 → 物理伤害加成
FGameplayAttributeData Intelligence; // 智力 → 法术伤害 / MaxMana
FGameplayAttributeData Resilience; // 韧性 → 防御力 / 护甲穿透
FGameplayAttributeData Vigor; // 活力 → 最大生命值
```
#### 4.3.3 URPGCombatAttributeSet
```cpp
// 战斗属性(由 Primary 派生 + 元属性)
FGameplayAttributeData Armor; // 防御
FGameplayAttributeData ArmorPenetration; // 穿透
FGameplayAttributeData BlockChance; // 格挡率
FGameplayAttributeData CriticalHitChance; // 暴击率
FGameplayAttributeData CriticalHitDamage; // 暴击伤害倍率
FGameplayAttributeData CriticalHitResistance; // 暴击抵抗
// Meta 属性(不复制,仅服务器临时使用)
FGameplayAttributeData Damage; // 临时伤害值
FGameplayAttributeData Healing; // 临时治疗值
```
#### 4.3.4 URPGResourceAttributeSet
```cpp
// 资源属性(当前值 + 上限 + 恢复速率)
FGameplayAttributeData Health, MaxHealth, HealthRegenRate;
FGameplayAttributeData Mana, MaxMana, ManaRegenRate;
FGameplayAttributeData Stamina, MaxStamina, StaminaRegenRate;
FGameplayAttributeData Shield, MaxShield, ShieldRegenRate;
// Damage 元属性移至 CombatAttributeSet
// MoveSpeed 保留在此或独立
FGameplayAttributeData MoveSpeed;
```
#### 4.3.5 迁移路径
现有代码中大量使用 `URPGAttributeSetBase::GetHealth()` 等接口。重构后:
1. 保留 `URPGAttributeSetBase` 作为 `deprecated` 别名(临时)
2.`ARPGCharacterBase` 中同时注册旧属性集和新属性集
3. 逐步将蓝图和 GE 引用迁移到新属性集
### 4.4 输入系统重构Tag 驱动)
#### 4.4.1 移除 EGSAbilityInputID
```cpp
// 删除EGSAbilityInputID 枚举
// 保留 Deprecated 版本一个版本周期用于迁移
// 新增URPGInputConfig DataAsset
UCLASS()
class URPGInputConfig : public UDataAsset {
// InputAction -> InputTag 映射
TArray<FRPGInputAction> AbilityInputActions;
// 根据 InputAction 查找 InputTag
FGameplayTag FindAbilityInputTagForAction(const UInputAction* InputAction) const;
};
```
#### 4.4.2 ASC 输入接口扩展
```cpp
// URPGAbilitySystemComponent 新增
void AbilityInputTagPressed(const FGameplayTag& InputTag);
void AbilityInputTagReleased(const FGameplayTag& InputTag);
void AbilityInputTagHeld(const FGameplayTag& InputTag);
void ProcessAbilityInput(float DeltaTime, bool bGamePaused);
void ClearAbilityInput();
```
#### 4.4.3 帧级输入缓冲
```cpp
// 三个缓冲数组,每帧统一处理
TArray<FGameplayAbilitySpecHandle> InputPressedSpecHandles;
TArray<FGameplayAbilitySpecHandle> InputReleasedSpecHandles;
TArray<FGameplayAbilitySpecHandle> InputHeldSpecHandles;
```
### 4.5 Activation Policy + Activation Group 系统
```cpp
// RPGGameplayAbility.h 替换现有布尔值
UENUM(BlueprintType)
enum class ERPGAbilityActivationPolicy : uint8 {
OnInputTriggered, // 替代 bActivateOnInput
WhileInputActive, // 新增(自动武器/冲刺)
OnSpawn, // 替代 bActivateAbilityOnGranted被动技能
};
UENUM(BlueprintType)
enum class ERPGAbilityActivationGroup : uint8 {
Independent,
Exclusive_Replaceable, // 激活时取消同组,可被替换
Exclusive_Blocking, // 激活时取消同组,不可被替换
};
// 在 URPGGameplayAbility 中
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Ability")
ERPGAbilityActivationPolicy ActivationPolicy = ERPGAbilityActivationPolicy::OnInputTriggered;
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category="Ability")
ERPGAbilityActivationGroup ActivationGroup = ERPGAbilityActivationGroup::Independent;
```
**兼容性**:现有的 `bActivateAbilityOnGranted``bActivateOnInput` 保留为 `deprecated`,迁移完成后删除。
### 4.6 Tag Relationship Mapping 系统
```cpp
// URPGAbilityTagRelationshipMapping - DataAsset
USTRUCT()
struct FRPGAbilityTagRelationship {
FGameplayTag AbilityTag; // 被测试的 Ability Tag
FGameplayTagContainer AbilityTagsToBlock; // 阻断这些 Tag 的能力
FGameplayTagContainer AbilityTagsToCancel; // 取消这些 Tag 的能力
FGameplayTagContainer ActivationRequiredTags; // 需要这些 Tag 才能激活
FGameplayTagContainer ActivationBlockedTags; // 有这些 Tag 时无法激活
};
// ASC 中使用
UPROPERTY() TObjectPtr<URPGAbilityTagRelationshipMapping> TagRelationshipMapping;
```
**实际应用示例**
- `Ability.Attack.Heavy``BlockTags: [Ability.Dodge]`(重击时无法翻滚)
- `Ability.Interact``BlockTags: [Ability.Attack.*]`(交互时禁止攻击)
- `Ability.Ultimate``RequiredTags: [Status.FullEnergy]`(蓄满才能放大招)
### 4.7 ExecCalc 扩展方案
```cpp
// RPGDamageExecutionCalc 扩展
// 输入Source.BaseDamage + CriticalHitChance/Damage
// 输入Target.Armor + ArmorPenetration + BlockChance + CritHitResistance
// 计算流程:
// 1. SetByCaller Damage 获取基础伤害
// 2. 计算暴击Rand < (CritHitChance - CritHitResistance) -> CritDamage 倍率
// 3. 计算格挡Rand < BlockChance -> 伤害减半
// 4. 计算护甲减免EffectiveArmor = Armor * (1 - ArmorPenetration)
// MitigatedDamage = BaseDamage * (100 / (100 + EffectiveArmor))
// 5. 通过 DynamicAssetTag 标记 Crit/Block 用于 UI/音效
// 6. 写入 Target.Damage 元属性
```
**可配置化**:将 `1.5f`(爆头倍率)、`"b_head"`(骨骼名)、护甲公式系数移至 `UGameplayTagsProjectSettings``URPGCombatSettings` DataAsset。
### 4.8 WidgetController MVC 架构
```cpp
// URPGWidgetController - 新基类
UCLASS(BlueprintType, Blueprintable)
class URPGWidgetController : public UObject {
protected:
UPROPERTY() TObjectPtr<APlayerController> PlayerController;
UPROPERTY() TObjectPtr<APlayerState> PlayerState;
UPROPERTY() TObjectPtr<UAbilitySystemComponent> AbilitySystemComponent;
UPROPERTY() TObjectPtr<UAttributeSet> AttributeSet;
public:
virtual void BroadcastInitialValues() {}
virtual void BindCallbacksToDependencies() {}
void SetWidgetControllerParams(const FRPGWidgetControllerParams& Params);
};
// 具体子类(蓝图中配置委托绑定)
UCLASS() class URPGHUDWidgetController : public URPGWidgetController {
// OnHealthChanged / OnMaxHealthChanged / OnManaChanged / ...
// VerbMessage 监听(伤害数字、击杀通知)
};
UCLASS() class URPGAttributeMenuWidgetController : public URPGWidgetController {
// AttributeInfo DataAsset 驱动的属性菜单
// BroadcastAttributeInfo() 推送所有属性数据
};
```
### 4.9 集中式 Tag 管理
```cpp
// RPGGameplayTags.h
namespace RPGGameplayTags {
// Ability 激活失败原因
RPGGAMEPLAYABILITY_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Ability_ActivateFail_IsDead);
RPGGAMEPLAYABILITY_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Ability_ActivateFail_Cooldown);
RPGGAMEPLAYABILITY_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Ability_ActivateFail_Cost);
RPGGAMEPLAYABILITY_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Ability_ActivateFail_TagsBlocked);
// 状态标签
RPGGAMEPLAYABILITY_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Status_Death);
RPGGAMEPLAYABILITY_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Status_Death_Dying);
RPGGAMEPLAYABILITY_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Status_Death_Dead);
RPGGAMEPLAYABILITY_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Status_KnockedDown);
RPGGAMEPLAYABILITY_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(Status_Interacting);
// 输入标签(通用)
RPGGAMEPLAYABILITY_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(InputTag_Jump);
RPGGAMEPLAYABILITY_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(InputTag_Sprint);
RPGGAMEPLAYABILITY_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(InputTag_Interact);
RPGGAMEPLAYABILITY_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(InputTag_PrimaryAction);
RPGGAMEPLAYABILITY_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(InputTag_SecondaryAction);
// SetByCaller
RPGGAMEPLAYABILITY_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(SetByCaller_Damage);
RPGGAMEPLAYABILITY_API UE_DECLARE_GAMEPLAY_TAG_EXTERN(SetByCaller_Heal);
}
```
替换现有的 DataTable Tag 注册机制或作为补充。现有5个 DataTableAbilityTags/DataTags/EffectTags/ObjectTags/StateTags可保留用于蓝图 Tag 注册C++ 关键 Tag 改用原生定义。
### 4.10 GlobalAbilitySystem 引入
```cpp
// URPGGlobalAbilitySystem : UWorldSubsystem
// 用途:全局 Buff/环境效果对所有角色生效
// 重生后自动重新应用全局效果
// 游戏模式可通过此系统广播全局技能/效果
```
---
## 五、新增功能建议
### 5.1 连击/输入缓冲系统FighterGame 核心需求)
```cpp
// URPGComboManagerComponent - 新增组件
// 管理连击状态机:
// - 当前连击节点
// - 输入缓冲窗口(帧数)
// - 连击链定义DataAsset
// 与 RPGAT_PlayMontageAndWaitForEvent 配合:
// - 蒙太奇播放到"连击窗口"事件 → 检查输入缓冲 → 激活下一段
```
**设计参考**UE5 的 `FInputBuffer` 或自定义 `TQueue<FGameplayTag>` 缓冲,配合 Activation Policy `Exclusive_Replaceable` 实现连击打断。
### 5.2 被动技能系统
已有 `bActivateAbilityOnGranted` 支持,重构后改为 `ActivationPolicy::OnSpawn`。扩展方向:
- **光环型被动**:持续 Infinite GE通过 `URPGGlobalAbilitySystem` 可广播
- **触发型被动**:监听 GameplayEvent Tag 触发(如"受击时触发反伤"
- **条件型被动**:基于 Tag 状态自动激活/失活
### 5.3 技能升级系统
```cpp
// URPGAbilityLevelComponent - 可选组件
// 管理每个 AbilitySpec 的等级
// AbilitySet 中声明 BaseLevel 和 MaxLevel
// 升级时RemoveAbility -> GiveAbility(Level+1) 或直接修改 Spec.Level
// 或使用 Aura 模式:
// AbilitySpec.Level 直接与角色等级绑定(在 GiveAbility 时设置)
```
### 5.4 Buff/Debuff 可视化管理
```cpp
// 当前问题ActiveGameplayEffects 存在 ASC 但无统一管理层
// 建议URPGActiveEffectsComponent
// 提供:
// - GetActiveBuffs() / GetActiveDebuffs()(按 Tag 分类)
// - 持续时间/层数的 UI 数据推送(通过 WidgetController
// - 效果到期/添加的 BlueprintAssignable 委托
```
---
## 六、重构实施计划
### 6.1 P0 — 立即修复1-2 天)
| 任务 | 文件 | 操作 |
|------|------|------|
| 修复 PURE_VIRTUAL 类名错误 | `RPGGATA_Trace.h` | `AGSGATA_Trace``ARPGGATA_Trace` |
| 清理 GS 前缀枚举 | `RPGAbilityTypes.h` | `EGSAbilityInputID``ERPGAbilityInputID`(或废弃) |
| 清理 GS 前缀委托 | `RPGAT_PlayMontageForMeshAndWaitForEvent.h` | `FGS*``FRPG*` |
| 清理注释中的 GASShooter 引用 | 多文件 | 全局搜索替换 |
| 移除无用 include | `RPGAbilityTypes.h` | 删除未使用的 Task include |
### 6.2 P1 — 核心重构1-2 周)
| 阶段 | 任务 | 优先级 |
|------|------|--------|
| 1.1 | 集中式 Tag 管理(`RPGGameplayTags.h` | 高(其他重构依赖此) |
| 1.2 | 属性集拆分Primary/Combat/Resource | 高 |
| 1.3 | MMC 实现MaxHealth/MaxMana 公式) | 中 |
| 1.4 | ActivationPolicy/Group 枚举引入 | 高 |
| 1.5 | ExecCalc 扩展(暴击/格挡/穿透) | 中 |
### 6.3 P2 — 架构升级2-3 周)
| 阶段 | 任务 | 优先级 |
|------|------|--------|
| 2.1 | InputConfig DataAsset + Tag 驱动输入 | 高 |
| 2.2 | ProcessAbilityInput 帧级缓冲 | 高 |
| 2.3 | AbilitySet DataAsset | 中 |
| 2.4 | Tag Relationship Mapping | 中 |
| 2.5 | WidgetController MVC 基类 | 中 |
| 2.6 | AdditionalCosts 可扩展 Cost 系统 | 低 |
### 6.4 P3 — 新功能(持续迭代)
| 功能 | 预估时间 |
|------|---------|
| GlobalAbilitySystem | 3 天 |
| 连击/输入缓冲系统 | 1 周 |
| 技能升级系统 | 1 周 |
| Buff/Debuff 可视化管理 | 3 天 |
### 6.5 兼容性策略
1. **保留旧接口**`bActivateAbilityOnGranted``bActivateOnInput` 保留 `UE_DEPRECATED` 一个版本
2. **渐进迁移**:旧属性集 `URPGAttributeSetBase` 保留为 `DEPRECATED`,指向新属性集组合
3. **单元测试**:重构每个子系统后立即编写 `.spec.cpp` 测试(至少覆盖 AttributeSet 的 Pre/PostGameplayEffectExecute
---
## 七、命名规范
### 7.1 类命名
| 类型 | 规范 | 示例 |
|------|------|------|
| Ability 类 | `URPGGA_` | `URPGGA_PrimaryAttack`, `URPGGA_CharacterJump` |
| AbilityTask | `URPGAT_` | `URPGAT_PlayMontageAndWaitForEvent` |
| AttributeSet | `URPG` + 职责 + `AttributeSet` | `URPGResourceAttributeSet` |
| ExecutionCalc | `URPG` + 功能 + `ExecCalc` | `URPGDamageExecCalc` |
| MMC | `URPGMMC_` | `URPGMMC_MaxHealth` |
| TargetActor | `URPGGATA_` | `URPGGATA_LineTrace` |
| WidgetController | `URPG` + 用途 + `WidgetController` | `URPGHUDWidgetController` |
| DataAsset | `URPG` + 内容 | `URPGAbilitySet`, `URPGInputConfig` |
### 7.2 GameplayTag 命名规范
```
[Category].[SubCategory].[SpecificName]
# Ability 激活失败原因
Ability.ActivateFail.IsDead
Ability.ActivateFail.Cooldown
# 技能行为标记
Ability.Behavior.SurvivesDeath
Ability.Behavior.Passive
# 输入标签
Input.Jump
Input.Sprint
Input.PrimaryAction
Input.SecondaryAction
# 状态标签
Status.Death.Dying
Status.Death.Dead
Status.KnockedDown
Status.Interacting
# 效果类标签
Effect.Damage.CanCrit
Effect.Damage.Crit
Effect.Damage.Blocked
# SetByCaller
SetByCaller.Damage
SetByCaller.Heal
# 属性标签(用于 Tag-to-Attribute 映射)
Attribute.Primary.Strength
Attribute.Combat.Armor
Attribute.Resource.Health
```
### 7.3 文件组织
```
Source/RPGGameplayAbility/
├── Public/Core/ ASC/Globals/CueManager/EffectContext
├── Public/Abilities/ Ability 基类 + AbilitySet + Policy
├── Public/Attributes/ 三层属性集
├── Public/Calculations/ ExecCalc + MMC
├── Public/Costs/ Cost 基类 + 实现
├── Public/Input/ InputConfig + InputComponent
├── Public/Tags/ 集中式 Tag 定义
├── Public/Target/ TargetType + TargetActor
├── Public/Tasks/ AbilityTask
├── Public/UI/ WidgetController
├── Public/Characters/ 角色基类
└── Public/Interfaces/ 接口Interactable/Combat/AbilitySource
```
---
## 八、参考资料
- [GASDocumentation by tranek](https://github.com/tranek/GASDocumentation) - GAS 最全面文档
- [Lyra Starter Game Source](D:\MatrixTA\LyraStarterGame\Source) - Epic 官方最佳实践
- [GASShooter](D:\MatrixTA\GASShooter) - 多武器/网络预测参考
- [UE5 GAS Aura](D:\MatrixTA\UE5_GAS_Aura-main) - RPG 属性体系参考
- [现有插件](D:\MatrixTA\MusicFighterGame\Project\Plugins\RPGGameplayAbility) - 重构对象