Files
BlueRoseNote/RPGGameplayAbility重构文档_Sonnet.md

1010 lines
37 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
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) - 重构对象