--- 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 变化监听 | ✅ 完成 | | **交互系统** | IRPGInteractable(Pre/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/弹药)、ARPG(XP/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 InputPressedSpecHandles; TArray InputReleasedSpecHandles; TArray InputHeldSpecHandles; // ProcessAbilityInput() 每帧统一处理: // 1. 检查 InputBlocked Tag // 2. 收集所有待激活 Ability(Held/Pressed) // 3. 统一 TryActivateAbility(避免顺序竞争) // 4. 转发 InputReleased 事件 // 5. 清空缓存 ``` 避免了逐 Ability 处理时的时间顺序竞争问题。 #### 2.1.3 InputTag 三层解耦架构 ``` UInputAction(EnhancedInput) → ULyraInputConfig(DataAsset) → InputTag(GameplayTag) → DynamicSpecSourceTags(注入 AbilitySpec) → ProcessAbilityInput(HasTagExact 匹配激活) ``` 策划可在数据层完全重组输入映射,无需修改代码。 #### 2.1.4 AbilitySet — 声明式模块化授权 ```cpp // 不可变 Data Asset,包含三种授予项 UPROPERTY() TArray GrantedGameplayAbilities; UPROPERTY() TArray GrantedGameplayEffects; UPROPERTY() TArray 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> 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 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> 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 DataAsset(InputAction ↔ 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 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 InputPressedSpecHandles; TArray InputReleasedSpecHandles; TArray 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 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 PlayerController; UPROPERTY() TObjectPtr PlayerState; UPROPERTY() TObjectPtr AbilitySystemComponent; UPROPERTY() TObjectPtr 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个 DataTable(AbilityTags/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` 缓冲,配合 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) - 重构对象