Files
BlueRoseNote/RPGGameplayAbility重构文档_Sonnet.md

37 KiB
Raw Blame History

tags, created, status, project
tags created status project
GAS
UE5
重构
技术文档
RPGGameplayAbility
2026-05-30 draft 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 宏类名错误

// RPGGATA_Trace.h - 错误的代码
PURE_VIRTUAL(AGSGATA_Trace::DoTrace, ...);      // ❌ 错误类名
PURE_VIRTUAL(AGSGATA_Trace::ShowDebugTrace, ...); // ❌ 错误类名

// 应该是:
PURE_VIRTUAL(ARPGGATA_Trace::DoTrace, ...);      // ✅

2. GASShooter 原始项目名残留

  • EGSAbilityInputIDGS 前缀来自 GASShooter
  • FGSPlayMontageForMeshAndWaitForEventDelegate
  • 注释中大量 AGSCharacterBaseGSAT_WaitTargetDataUsingActor 引用
  • 头文件注释 #include "GASShooter/GASShooter.h" 残留

P1中优先级问题

3. 上帝属性集反模式

URPGAttributeSetBase 将 20 个属性塞入单个类混合了射击游戏Armor/弹药、ARPGXP/Gold、格斗游戏Stamina的属性。职责不清难以按游戏类型裁剪。

4. 枚举与游戏类型强耦合

UENUM(BlueprintType)
enum class EGSAbilityInputID : uint8 {
    None,
    Confirm, Cancel,
    PrimaryFire, SecondaryFire, Reload,   // 射击游戏专用
    NextWeapon, PrevWeapon,               // 武器切换
    Sprint, Jump, Interact,               // 通用动作
    Crouch                               // 但对格斗游戏无意义
};

对于 FighterGamePrimaryFire/Reload/NextWeapon 等枚举完全不适用,浪费枚举空间且产生误导。

5. 命名不一致

错误 位置
EGSAbilityInputIDGS 前缀) RPGAbilityTypes.h
FAbilityMeshMontage(无前缀) RPGAbilitySystemComponent.h
FGSPlayMontageForMeshAndWaitForEvent*GS 前缀) RPGAT_PlayMontageForMeshAndWaitForEvent.h

P2低优先级问题

6. 硬编码值

// RPGDamageExecutionCalc.cpp
const float HeadShotMultiplier = 1.5f;               // 不可配置
const FName BoneName = "b_head";                     // 硬编码骨骼名
// 护甲减伤公式 100/(100+Armor) 硬编码

7. 死代码

// 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 双维控制

// 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 帧级输入缓冲机制

// 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 — 声明式模块化授权

// 不可变 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。策划修改技能互斥关系无需编译代码。

// 激活 Ability 时动态扩展 Block/Cancel Tags
void ApplyAbilityBlockAndCancelTags(...) override {
    if (TagRelationshipMapping) {
        TagRelationshipMapping->GetAbilityTagsToBlockAndCancel(
            AbilityTags, &ModifiedBlockTags, &ModifiedCancelTags);
    }
    Super::ApplyAbilityBlockAndCancelTags(...);
}

2.1.6 Meta Attribute 管线 + HideFromModifiers

// 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 分发

// WorldSubsystem管理全局 GE/Ability 分发
void RegisterASC(ULyraAbilitySystemComponent* ASC) {
    // 自动将已有全局效果施加到新注册的 ASC
    // 支持角色重生后自动重新应用
}

2.1.8 AdditionalCosts 可扩展 Cost 系统

UPROPERTY(EditDefaultsOnly, Instanced, Category=Costs)
TArray<TObjectPtr<ULyraAbilityCost>> AdditionalCosts;

// ShouldOnlyApplyCostOnHit - 远程武器未命中时不消耗弹药

2.1.9 VerbMessage 广播模式

// PostGameplayEffectExecute 中通过 GameplayMessageSubsystem 广播
UGameplayMessageSubsystem::BroadcastMessage(
    TAG_Lyra_Damage_Message,
    FLyraVerbMessage{Instigator, Target, Magnitude, Tags}
);

非耦合的伤害事件分发UI/音频/统计系统各自监听。

2.2 GASShooter — 射击类 GAS 最佳实践

2.2.1 EffectContainer 系统

// GSAbilityTypes.h - 声明式 GE 映射
TMap<FGameplayTag, FGSGameplayEffectContainer> EffectContainerMap;

// 运行时应用流程:
// MakeEffectContainerSpec(Tag) -> TargetType::GetTargets() -> MakeEffectSpec
// ApplyEffectContainerSpec(Spec) -> K2_ApplyGameplayEffectSpecToTarget

将技能效果配置数据驱动化,蓝图设计师无需手动编写 GE 应用代码。

2.2.2 武器作为能力授予者

// AGSWeapon 实现 IAbilitySystemInterface
// bSourceObjectMustEqualCurrentWeaponToActivate 确保武器绑定
// 卸载武器时自动 ClearAbility

2.2.3 弹药作为独立属性集

// GSAmmoAttributeSet.h - 独立弹药属性集
UPROPERTY() FGameplayAttributeData RifleReserveAmmo;
UPROPERTY() FGameplayAttributeData MaxRifleReserveAmmo;
// GetReserveAmmoAttributeFromTag() - Tag 到属性的动态映射

2.2.4 PreReplication 网络优化

// 开火时禁用弹夹复制,减少带宽消耗
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 公式化属性派生

// 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

// AuraEffectActor.h - 策略枚举控制 GE 应用
UPROPERTY(EditAnywhere) EEffectApplicationPolicy InstantEffectApplicationPolicy;
// ApplyOnOverlap / ApplyOnEndOverlap / DoNotApply

UPROPERTY(EditAnywhere) EEffectRemovalPolicy InfiniteEffectRemovalPolicy;
// RemoveOnEndOverlap / DoNotRemove

无需蓝图代码即可配置药水/Buff 区域/光环。

2.3.5 集中式 Tag 管理

// 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 运行时映射

// 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 DataAssetUInputActionFGameplayTag 映射)
  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_TagStackTag 栈计数,用于弹药/特殊资源)

四、重构方案设计

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新基类

// 参考 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

// 4 个基础属性,驱动 Secondary 属性的 MMC 计算
FGameplayAttributeData Strength;       // 力量 → 物理伤害加成
FGameplayAttributeData Intelligence;   // 智力 → 法术伤害 / MaxMana
FGameplayAttributeData Resilience;     // 韧性 → 防御力 / 护甲穿透
FGameplayAttributeData Vigor;          // 活力 → 最大生命值

4.3.3 URPGCombatAttributeSet

// 战斗属性(由 Primary 派生 + 元属性)
FGameplayAttributeData Armor;                  // 防御
FGameplayAttributeData ArmorPenetration;       // 穿透
FGameplayAttributeData BlockChance;            // 格挡率
FGameplayAttributeData CriticalHitChance;      // 暴击率
FGameplayAttributeData CriticalHitDamage;      // 暴击伤害倍率
FGameplayAttributeData CriticalHitResistance;  // 暴击抵抗

// Meta 属性(不复制,仅服务器临时使用)
FGameplayAttributeData Damage;    // 临时伤害值
FGameplayAttributeData Healing;   // 临时治疗值

4.3.4 URPGResourceAttributeSet

// 资源属性(当前值 + 上限 + 恢复速率)
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

// 删除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 输入接口扩展

// 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 帧级输入缓冲

// 三个缓冲数组,每帧统一处理
TArray<FGameplayAbilitySpecHandle> InputPressedSpecHandles;
TArray<FGameplayAbilitySpecHandle> InputReleasedSpecHandles;
TArray<FGameplayAbilitySpecHandle> InputHeldSpecHandles;

4.5 Activation Policy + Activation Group 系统

// 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;

兼容性:现有的 bActivateAbilityOnGrantedbActivateOnInput 保留为 deprecated,迁移完成后删除。

4.6 Tag Relationship Mapping 系统

// 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.HeavyBlockTags: [Ability.Dodge](重击时无法翻滚)
  • Ability.InteractBlockTags: [Ability.Attack.*](交互时禁止攻击)
  • Ability.UltimateRequiredTags: [Status.FullEnergy](蓄满才能放大招)

4.7 ExecCalc 扩展方案

// 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"(骨骼名)、护甲公式系数移至 UGameplayTagsProjectSettingsURPGCombatSettings DataAsset。

4.8 WidgetController MVC 架构

// 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 管理

// 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 引入

// URPGGlobalAbilitySystem : UWorldSubsystem
// 用途:全局 Buff/环境效果对所有角色生效
// 重生后自动重新应用全局效果
// 游戏模式可通过此系统广播全局技能/效果

五、新增功能建议

5.1 连击/输入缓冲系统FighterGame 核心需求)

// 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 技能升级系统

// URPGAbilityLevelComponent - 可选组件
// 管理每个 AbilitySpec 的等级
// AbilitySet 中声明 BaseLevel 和 MaxLevel
// 升级时RemoveAbility -> GiveAbility(Level+1) 或直接修改 Spec.Level

// 或使用 Aura 模式:
// AbilitySpec.Level 直接与角色等级绑定(在 GiveAbility 时设置)

5.4 Buff/Debuff 可视化管理

// 当前问题ActiveGameplayEffects 存在 ASC 但无统一管理层
// 建议URPGActiveEffectsComponent
// 提供:
//   - GetActiveBuffs() / GetActiveDebuffs()(按 Tag 分类)
//   - 持续时间/层数的 UI 数据推送(通过 WidgetController
//   - 效果到期/添加的 BlueprintAssignable 委托

六、重构实施计划

6.1 P0 — 立即修复1-2 天)

任务 文件 操作
修复 PURE_VIRTUAL 类名错误 RPGGATA_Trace.h AGSGATA_TraceARPGGATA_Trace
清理 GS 前缀枚举 RPGAbilityTypes.h EGSAbilityInputIDERPGAbilityInputID(或废弃)
清理 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. 保留旧接口bActivateAbilityOnGrantedbActivateOnInput 保留 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

八、参考资料