From 6e372d87511e5ff653558378dfd8078737c85e11 Mon Sep 17 00:00:00 2001 From: BlueRose <378100977@qq.com> Date: Sat, 30 May 2026 22:33:48 +0800 Subject: [PATCH] vault backup: 2026-05-30 22:33:48 --- RPGGameplayAbility重构文档.md | 909 +++++++++++++++++++++++ RPGGameplayAbility重构文档_Sonnet.md | 1009 ++++++++++++++++++++++++++ 2 files changed, 1918 insertions(+) create mode 100644 RPGGameplayAbility重构文档.md create mode 100644 RPGGameplayAbility重构文档_Sonnet.md diff --git a/RPGGameplayAbility重构文档.md b/RPGGameplayAbility重构文档.md new file mode 100644 index 0000000..085101c --- /dev/null +++ b/RPGGameplayAbility重构文档.md @@ -0,0 +1,909 @@ +--- +tags: + - GAS + - UE5 + - 架构 + - 重构 + - 插件 +date: 2026-05-30 +project: MusicFighterGame +plugin: RPGGameplayAbility +status: 设计阶段 +--- + +# RPGGameplayAbility 插件重构文档 + +## 概述 + +本文档基于对以下三个 UE5 项目的深度研究,分析其 GameplayAbilitySystem (GAS) 架构、插件设计和技术亮点,并对 `RPGGameplayAbility` 插件提出全面的重构建议。 + +### 研究项目 + +| 项目 | 类型 | 亮点 | +|------|------|------| +| [[LyraStarterGame]] | Epic 官方 UE5 示例 | GameFeature 模块化、GameplayTag 输入路由、装备系统、GamePhase | +| [[GASShooter]] | Epic 官方 UE4 射击示例 | 多 Mesh 蒙太奇、武器能力授予、EffectContainer、可重用 TargetActor | +| [[UE5_GAS_Aura]] | 社区 RPG 教程项目 | 三层属性模型、MMC 派生属性、MVVC WidgetController、DataAsset 驱动 | + +### 当前插件现状 + +`RPGGameplayAbility` 插件基于 GASShooter 框架衍生,已具备: + +- ✅ 多 Mesh 蒙太奇复制系统 +- ✅ EffectContainer + TargetType 效果容器系统 +- ✅ RPC 批处理 (`ShouldDoServerAbilityRPCBatch`) +- ✅ 伤害元属性模式 (DamageExecutionCalc) +- ✅ 可重用 GATA_Trace 瞄准 Actor +- ✅ GameplayMessageSubsystem 基础设施 + +但存在以下核心架构问题: + +- ❌ 硬编码 `EGSAbilityInputID` 枚举输入绑定 +- ❌ 单一巨型属性集 (18 个属性) +- ❌ 角色基类手动维护 15+ 个属性 getter 函数 +- ❌ 无 AbilitySet DataAsset 模块化能力配置 +- ❌ LoadingScreen 模块耦合在 gameplay 插件中 +- ❌ 无 GameplayTag 驱动的输入路由 +- ❌ 无 MVVM/WidgetController UI 模式 +- ❌ 无装备/武器系统与 GAS 集成 +- ❌ 无队伍/阵营系统 +- ❌ 无 GamePhase 阶段管理 +- ❌ 硬编码骨骼名称 (`"b_head"`) + +--- + +## 核心重构优先级 + +### 优先级 1:GameplayTag 输入路由替换硬编码枚举 + +> [!important] 最高优先级 +> 这是影响最大的单一改动,Lyra 和 Aura 都采用此模式。 + +**当前实现(差):** + +```cpp +// RPGAbilityTypes.h +UENUM(BlueprintType) +enum class EGSAbilityInputID : uint8 { + None = 0, Confirm = 1, Cancel = 2, + Sprint = 3, Jump = 4, PrimaryFire = 5, + SecondaryFire = 6, AlternateFire = 7, + Reload = 8, NextWeapon = 9, PrevWeapon = 10, + Interact = 11 +}; +``` + +**推荐实现(Lyra 模式):** + +```cpp +// RPGInputConfig.h - DataAsset 驱动 +USTRUCT(BlueprintType) +struct FRPGInputAction { + UPROPERTY(EditDefaultsOnly) + TObjectPtr InputAction; + + UPROPERTY(EditDefaultsOnly) + FGameplayTag InputTag; +}; + +UCLASS(BlueprintType) +class URPGInputConfig : public UDataAsset { + UPROPERTY(EditDefaultsOnly) + TArray AbilityInputActions; + + UPROPERTY(EditDefaultsOnly) + TArray NativeInputActions; +}; + +// RPGInputComponent.h - 模板绑定 +class URPGInputComponent : public UEnhancedInputComponent { + template + void BindAbilityActions(const URPGInputConfig* InputConfig, + UserClass* Object, PressedFuncType PressedFunc, + ReleasedFuncType ReleasedFunc, HeldFuncType HeldFunc); +}; + +// RpgAbilitySystemComponent.h - ASC 输入处理 +void URPGAbilitySystemComponent::AbilityInputTagPressed(FGameplayTag InputTag) { + for (FGameplayAbilitySpec& Spec : ActivatableAbilities.Items) { + if (Spec.GetDynamicSpecSourceTags().HasTagExact(InputTag)) { + Spec.InputPressed = true; + if (Spec.IsActive()) { + AbilitySpecInputPressed(Spec); + } else { + TryActivateAbility(Spec.Handle); + } + } + } +} +``` + +**优势:** +- 新增能力无需重新编译枚举 +- 输入可通过 DataAsset 按角色重新绑定 +- GameFeature 插件可在不接触核心代码的情况下添加新输入标签 +- 支持 Pressed/Held/Released 三种策略(类似 Aura 的 `AbilityInputTagHeld`/`Released`) + +--- + +### 优先级 2:拆分巨型属性集 + +> [!important] 核心架构改动 +> Aura 的三层属性模型是 RPG 游戏的标准做法。 + +**当前问题:** `RPGAttributeSetBase` 包含 18 个属性,混在一起不可拆分。 + +**推荐结构:** + +```cpp +// 第一层:主要属性(可投入加点的属性) +UCLASS() +class URPGVitalAttributeSet : public UAttributeSet { + // Health, MaxHealth, HealthRegenRate + // Mana, MaxMana, ManaRegenRate + // Stamina, MaxStamina, StaminaRegenRate + // Shield, MaxShield, ShieldRegenRate +}; + +// 第二层:次要属性(通过 MMC 派生的战斗属性) +UCLASS() +class URPGCombatAttributeSet : public UAttributeSet { + // Armor, ArmorPenetration + // CritChance, CritDamage, CritResistance + // BlockChance + // MoveSpeed +}; + +// 第三层:主要属性(核心加点属性) +UCLASS() +class URPGPrimaryAttributeSet : public UAttributeSet { + // Strength, Intelligence, Agility, Vitality +}; + +// Meta 属性(临时、非复制、仅服务器) +UCLASS() +class URPGMetaAttributeSet : public UAttributeSet { + // Damage (meta, 仅服务器) + // Healing (meta, 仅服务器) +}; + +// 进度属性 +UCLASS() +class URPGProgressionAttributeSet : public UAttributeSet { + // CharacterLevel, XP, Gold +}; +``` + +**MMC 派生属性计算(Aura 模式):** + +```cpp +// MMC_MaxHealth.cpp +float UMMC_MaxHealth::CalculateBaseMagnitude_Implementation( + const FGameplayEffectSpec& Spec) const { + + float Vitality = 0.f; + GetCapturedAttributeMagnitude( + VitalityDef, Spec, FAggregatorEvaluateParameters(), Vitality); + + int32 Level = 1; + if (Spec.GetContext().GetSourceObject()) { + // 通过 ICombatInterface 获取等级 + } + + return 80.f + 2.5f * Vitality + 10.f * Level; +} +``` + +--- + +### 优先级 3:引入 AbilitySet DataAsset + +> [!important] 模块化配置 +> 替换硬编码的 `CharacterAbilities` 数组。 + +```cpp +USTRUCT(BlueprintType) +struct FRPGGameplayAbilitySet_GameplayAbility { + UPROPERTY(EditDefaultsOnly) + TSubclassOf Ability; + + UPROPERTY(EditDefaultsOnly) + int32 AbilityLevel = 1; + + UPROPERTY(EditDefaultsOnly) + FGameplayTag InputTag; + + UPROPERTY(EditDefaultsOnly) + ERPGAbilityActivationPolicy ActivationPolicy; +}; + +USTRUCT(BlueprintType) +struct FRPGGameplayAbilitySet_GameplayEffect { + UPROPERTY(EditDefaultsOnly) + TSubclassOf GameplayEffect; + + UPROPERTY(EditDefaultsOnly) + float EffectLevel = 1.f; +}; + +USTRUCT(BlueprintType) +struct FRPGGameplayAbilitySet_AttributeSet { + UPROPERTY(EditDefaultsOnly) + TSubclassOf AttributeSet; +}; + +UCLASS(BlueprintType) +class URPGGameplayAbilitySet : public UPrimaryDataAsset { + GENERATED_BODY() +public: + UPROPERTY(EditDefaultsOnly) + TArray GrantedAbilities; + + UPROPERTY(EditDefaultsOnly) + TArray GrantedEffects; + + UPROPERTY(EditDefaultsOnly) + TArray GrantedAttributes; + + void GiveToAbilitySystem( + URPGAbilitySystemComponent* ASC, + FRPGGameplayAbilitySet_GrantedHandles& OutHandles, + UObject* SourceObject = nullptr) const; + + void TakeFromAbilitySystem( + FRPGGameplayAbilitySet_GrantedHandles& Handles) const; +}; +``` + +**使用场景:** +- 角色职业定义:`DA_FighterAbilitySet`、`DA_MageAbilitySet` +- 武器/装备授予:装备授予 `DA_SwordAbilitySet` +- 被动技能树:技能树节点授予特定的 AbilitySet +- Buff/Debuff:临时添加/移除 AbilitySet + +--- + +### 优先级 4:MVVM WidgetController UI 模式 + +> [!important] UI 解耦 +> 当前插件直接在角色代码中 push UI 数据,耦合度高。 + +**Aura 的 WidgetController 架构:** + +``` +┌─────────────────────────────────────────────────┐ +│ FWidgetControllerParams(模型数据) │ +│ - PlayerController │ +│ - PlayerState │ +│ - AbilitySystemComponent │ +│ - AttributeSet │ +└──────────────┬──────────────────────────────────┘ + │ +┌──────────────▼──────────────────────────────────┐ +│ URPGWidgetController(ViewModel 基类) │ +│ - BroadcastInitialValues() │ +│ - BindCallbacksToDependencies() │ +│ - 所有权:PlayerController │ +└──────────────┬──────────────────────────────────┘ + │ + ┌──────────┴──────────┐ + │ │ +┌───▼──────────┐ ┌──────▼──────────┐ +│ OverlayWidget │ │ AttributeMenu │ +│ Controller │ │ WidgetController│ +│ - Health/Mana │ │ - 动态属性菜单 │ +│ - Messages │ │ - TagsToAttrs │ +└───┬───────────┘ └──────┬──────────┘ + │ │ +┌───▼─────────────────────▼──────────────────────┐ +│ URPGUserWidget(View - UMG Blueprint) │ +│ - SetWidgetController() 事件 │ +│ - 绑定 BlueprintAssignable 委托 │ +└─────────────────────────────────────────────────┘ +``` + +**HUD 工厂模式:** + +```cpp +UCLASS() +class ARPGHUD : public AHUD { + // 懒加载单例工厂 + UOverlayWidgetController* GetOverlayWidgetController( + const FRPGWidgetControllerParams& Params); + + UAttributeMenuWidgetController* GetAttributeMenuWidgetController( + const FRPGWidgetControllerParams& Params); +}; +``` + +--- + +### 优先级 5:插件模块拆分 + +**当前问题:** 5 个模块(RPGGameplayAbility、CommonLoadingScreen、CommonStartupLoadingScreen、GameplayMessageRuntime、GameplayMessageNodes)全部在一个插件中。 + +**推荐结构:** + +``` +Plugins/ +├── RPGGameplayAbility/ # 核心 GAS 扩展 +│ ├── Source/ +│ │ └── RPGGameplayAbility/ # 唯一模块 +│ └── RPGGameplayAbility.uplugin +│ +├── CommonLoadingScreen/ # 独立加载画面插件 +│ └── CommonLoadingScreen.uplugin +│ +├── CommonStartupLoadingScreen/ # 独立启动加载画面插件 +│ └── CommonStartupLoadingScreen.uplugin +│ +└── GameplayMessageRouter/ # 消息路由器(保持独立) + ├── GameplayMessageRuntime/ + └── GameplayMessageNodes/ +``` + +--- + +## 各系统详细重构建议 + +### 1. ASC 扩展 (URPGAbilitySystemComponent) + +**保留:** +- 多 Mesh 蒙太奇复制系统(格斗游戏需要 1P/3P 双骨骼) +- RPC 批处理 (`ShouldDoServerAbilityRPCBatch`) +- Blueprint 标签操作辅助函数 +- 本地 GameplayCue 执行 + +**新增(来自 Lyra):** + +| 功能 | 说明 | +|------|------| +| `AbilityInputTagPressed/Released/Held` | GameplayTag 驱动的输入处理 | +| `ProcessAbilityInput(DeltaTime)` | 每帧统一的输入分发 | +| 激活组系统 | Independent / Exclusive_Replaceable / Exclusive_Blocking | +| 动态 Tag GE 应用 | 运行时 Tag 管理 | +| TagRelationshipMapping 支持 | 跨能力阻塞/取消关系 | + +**新增(来自 Aura):** + +| 功能 | 说明 | +|------|------| +| `ClientEffectApplied` RPC | GE 应用时客户端通知 UI | +| `m_EffectAssetTag` 多播委托 | Widget 创建触发 | + +**激活组系统(格斗游戏关键):** + +```cpp +UENUM(BlueprintType) +enum class ERPGAbilityActivationGroup : uint8 { + Independent, // 不阻塞任何能力,不被任何能力阻塞 + Exclusive_Replaceable, // 可被其他 Exclusive 能力取消 + Exclusive_Blocking, // 阻塞其他 Exclusive 能力,自身不可被取消 +}; + +// 使用场景: +// - 普通攻击:Independent(可叠加) +// - 必杀技:Exclusive_Replaceable(会被新必杀技取消) +// - 超必杀技:Exclusive_Blocking(不可取消,阻塞其他技能) +// - 防御/受击:Exclusive_Blocking(不可取消) +``` + +--- + +### 2. GameplayAbility 基类 (URPGGameplayAbility) + +**保留:** +- EffectContainer 系统(Tag → TargetType + GEs) +- 自定义 Cost 检查(RPGCheckCost/RPGApplyCost BlueprintNativeEvent) +- 多 Mesh 动画辅助函数 + +**新增(来自 Lyra):** + +```cpp +UENUM(BlueprintType) +enum class ERPGAbilityActivationPolicy : uint8 { + OnInputTriggered, // 按键按下触发 + WhileInputActive, // 按键持续期间激活 + OnSpawn, // 授予时立即激活(被动能力) + OnRhythmBeat, // 节奏节拍触发(MusicFighter 特有) +}; + +// 组合式 Cost 系统 +UCLASS(Abstract, EditInlineNew, DefaultToInstanced) +class URPGAbilityCost : public UObject { + virtual bool CheckCost(const URPGGameplayAbility* Ability, + const FGameplayAbilitySpecHandle Handle, + const FGameplayAbilityActorInfo* ActorInfo, + FGameplayTagContainer* OptionalRelevantTags) const; + + virtual void ApplyCost(const URPGGameplayAbility* Ability, + const FGameplayAbilitySpecHandle Handle, + const FGameplayAbilityActorInfo* ActorInfo, + const FGameplayAbilityActivationInfo ActivationInfo); +}; + +// 子类: +// - URPGAbilityCost_GameplayEffect(GE 消耗) +// - URPGAbilityCost_ItemTagStack(物品标记栈消耗,如弹药) +// - URPGAbilityCost_Attribute(直接属性消耗,如怒气值) +``` + +**删除/替换:** +- `EGSAbilityInputID AbilityInputID` → `FGameplayTag StartupInputTag` +- `bActivateOnInput` → `ERPGAbilityActivationPolicy ActivationPolicy` +- `bSourceObjectMustEqualCurrentWeaponToActivate` → 泛化为 Tag 需求检查 + +--- + +### 3. 属性系统 - 完整重构 + +``` +Primary Attributes(主要/可投资属性) +├── Strength → 影响 PhysicalAttack, MaxHealth +├── Intelligence → 影响 MagicAttack, MaxMana +├── Agility → 影响 CritChance, MoveSpeed, DodgeChance +└── Vitality → 影响 MaxHealth, MaxStamina, HealthRegenRate + +Secondary Attributes(派生/战斗属性 - 通过 MMC 计算) +├── MaxHealth = f(Vitality, Level) +├── MaxMana = f(Intelligence, Level) +├── MaxStamina = f(Vitality, Level) +├── PhysicalAttack = f(Strength, Level) +├── MagicAttack = f(Intelligence, Level) +├── Armor = f(Agility, Vitality, Level) +├── ArmorPenetration = f(Strength, Level) +├── CritChance = f(Agility, Level) +├── CritDamage = 1.5x (基础) + 装备加成 +├── CritResistance = f(Vitality, Level) +├── BlockChance = f(Strength, Level) +├── DodgeChance = f(Agility, Level) +└── MoveSpeed = Base(400) + f(Agility, Level) + +Vital Attributes(运行时资源) +├── Health → [0, MaxHealth] +├── Mana → [0, MaxMana] +└── Stamina → [0, MaxStamina] + +Meta Attributes(临时,服务器专用) +├── Damage → ExecutionCalc 写入 → PostGameplayEffectExecute 处理后归零 +└── Healing → HealingExecutionCalc 写入 → 处理后归零 + +Progression(进度) +├── CharacterLevel → 影响所有 MMC 计算 +├── XP → 经验值 +└── Gold → 货币 +``` + +**伤害计算管道:** + +``` +1. 技能设置 SetByCaller Magnitude (Tag: "Data.Damage") +2. URPGDamageExecutionCalc 捕获: + - Source: PhysicalAttack/MagicAttack + - Target: Armor, ArmorPenetration, CritResistance, BlockChance, DodgeChance +3. 计算流程: + a. 命中判定 (DodgeChance) + b. 暴击判定 (CritChance vs CritResistance) + c. 格挡判定 (BlockChance) + d. 护甲减免 (Armor vs ArmorPenetration) + e. 属性克制修正(元素标签) + f. 最终伤害写入 Target.Damage +4. PostGameplayEffectExecute: + a. Shield 吸收 + b. Health 扣减 → Clamp + c. 存活/死亡判定 → 广播 (GameplayMessageSubsystem) +``` + +--- + +### 4. 瞄准系统 + +**保留:** +- `URPGTargetType` 蓝图化瞄准逻辑 +- `RPGATA_Trace` / `RPGATA_LineTrace` / `RPGATA_SphereTrace` + +**新增(格斗游戏专用):** + +```cpp +// 近战弧形瞄准 +UCLASS(Blueprintable) +class URPGTargetType_MeleeArc : public URPGTargetType { + UPROPERTY(EditDefaultsOnly) + float ArcAngle = 90.f; // 弧形角度 + + UPROPERTY(EditDefaultsOnly) + float ArcRadius = 200.f; // 弧形半径 +}; + +// AOE 圆形瞄准 +UCLASS(Blueprintable) +class URPGTargetType_CircleAOE : public URPGTargetType { + UPROPERTY(EditDefaultsOnly) + float Radius = 300.f; +}; + +// 组合状态过滤 +// "已在此连招中被击中过的目标不重复选取" +void GetTargets_Implementation(...) { + // 检查 Combat.AlreadyHit 标签 + for (AActor* Target : Candidates) { + if (!Target->HasMatchingGameplayTag(Combat_AlreadyHit)) { + OutActors.Add(Target); + } + } +} +``` + +--- + +### 5. 输入系统 + +**替换整个 `EGSAbilityInputID` 枚举为以下架构:** + +``` +┌─────────────────────────┐ +│ URPGInputConfig │ DataAsset +│ - AbilityInputActions │ 映射 InputAction → GameplayTag +│ - NativeInputActions │ +└───────────┬─────────────┘ + │ +┌───────────▼─────────────┐ +│ URPGInputComponent │ extends UEnhancedInputComponent +│ - BindAbilityActions() │ 模板函数,自动绑定 +└───────────┬─────────────┘ + │ +┌───────────▼─────────────┐ +│ ULyraHeroComponent │ (或 RPGHeroComponent) +│ - InitializePlayerInput│ +└───────────┬─────────────┘ + │ +┌───────────▼─────────────┐ +│ URPGAbilitySystemComp │ +│ - AbilityInputTagPressed│ 匹配 DynamicSpecSourceTags +│ - AbilityInputTagReleased│ +│ - AbilityInputTagHeld │ +│ - ProcessAbilityInput │ 每帧统一处理 +└─────────────────────────┘ +``` + +**MusicFighter 特有:节奏输入缓冲** + +```cpp +// 在 ProcessAbilityInput 中 +void URPGAbilitySystemComponent::ProcessAbilityInput(float DeltaTime, bool bGamePaused) { + // ... 标准处理 ... + + // 节奏检测 + if (bIsOnBeat) { + for (FGameplayAbilitySpec& Spec : ActivatableAbilities.Items) { + if (Spec.Ability->GetActivationPolicy() == OnRhythmBeat) { + // 应用节奏加成标签 + Spec.DynamicSpecSourceTags.AddTag(RhythmBonusTag); + } + } + } + + // 输入缓冲(格斗游戏标准做法) + FlushInputBuffer(DeltaTime); +} +``` + +--- + +### 6. UI 系统 + +**当前问题:** 直接在 Character/PlayerState/PlayerController 中 push UI 数据。 + +**使用 Aura 的 MVVC 模式替换:** + +```cpp +// WidgetController 管理 ASC 委托绑定 +// Widget (UMG) 仅负责显示 +// 中间通过 BlueprintAssignable 委托通信 + +// 消息 Widget 通过 DataTable 驱动: +USTRUCT(BlueprintType) +struct FRPGMessageWidgetRow : public FTableRowBase { + UPROPERTY(EditAnywhere) + FGameplayTag MessageTag; + + UPROPERTY(EditAnywhere) + TSubclassOf MessageWidgetClass; + + UPROPERTY(EditAnywhere) + UTexture2D* MessageImage; + + UPROPERTY(EditAnywhere) + FText MessageText; +}; +``` + +**GameplayMessageSubsystem 集成:** + +```cpp +// 替换直接调用 PC->ShowDamageNumber(...) +// 使用消息通道广播: +UGameplayMessageSubsystem::Get(this).BroadcastMessage( + RPGGameplayTags::Get().DamageDealt, + FRPGDamageMessage{ + Instigator, Target, Damage, DamageTags + } +); + +// UI Widget 订阅: +UGameplayMessageSubsystem::Get(this).RegisterListener( + RPGGameplayTags::Get().DamageDealt, + this, &URPGDamageWidget::OnDamageMessage +); +``` + +--- + +### 7. 装备系统 + +> [!note] 新增功能 +> 当前插件无装备系统,使用 Lyra 模式新增。 + +```cpp +// 装备定义(DataAsset) +UCLASS(BlueprintType) +class URPGEquipmentDefinition : public UObject { + UPROPERTY(EditDefaultsOnly) + TSubclassOf InstanceType; + + UPROPERTY(EditDefaultsOnly) + TArray AbilitySetsToGrant; + + UPROPERTY(EditDefaultsOnly) + TArray ActorsToSpawn; +}; + +// 装备实例(运行时) +UCLASS(BlueprintType) +class URPGEquipmentInstance : public UObject { + // 授予的能力句柄 + FRPGGameplayAbilitySet_GrantedHandles GrantedHandles; + + // 关联的源对象(武器/乐器/道具) + UObject* GetInstigator() const; +}; + +// 装备管理器组件(挂在 Pawn 上) +UCLASS() +class URPGEquipmentManagerComponent : public UPawnComponent { + UFUNCTION(BlueprintCallable) + void EquipItem(TSubclassOf EquipmentDef); + + UFUNCTION(BlueprintCallable) + void UnequipItem(URPGEquipmentInstance* EquipmentInstance); +}; + +// 装备能力基类 +UCLASS() +class URPGGameplayAbility_FromEquipment : public URPGGameplayAbility { + // 可反查装备实例获取属性/状态 + URPGEquipmentInstance* GetAssociatedEquipment() const; +}; +``` + +--- + +### 8. GamePhase 阶段系统 + +> [!note] 新增功能 +> 音乐格斗游戏需要回合管理。 + +```cpp +UCLASS() +class URPGamePhaseSubsystem : public UWorldSubsystem { + // 使用层级 GameplayTag 管理阶段 + // Game.WaitingForPlayers + // Game.Countdown + // Game.Playing.Round1 + // Game.Playing.Round1.Break + // Game.Playing.Round2 + // Game.ShowingResult + + void StartPhase(TSubclassOf PhaseAbility, + FRPGamePhaseDelegate PhaseEndedCallback); + + void WhenPhaseStartsOrIsActive(FGameplayTag PhaseTag, + EPhaseTagMatchType MatchType, + const FRPGamePhaseTagDelegate& WhenActive); + + void WhenPhaseEnds(FGameplayTag PhaseTag, + EPhaseTagMatchType MatchType, + const FRPGamePhaseTagDelegate& WhenEnd); +}; + +// 阶段能力 +UCLASS() +class URPGamePhaseAbility : public URPGGameplayAbility { + // ReplicationPolicy = ReplicateNo + // NetExecutionPolicy = ServerInitiated + // NetSecurityPolicy = ServerOnly + + UPROPERTY(EditDefaultsOnly) + FGameplayTag GamePhaseTag; +}; +``` + +**能力阶段门控:** +- `ActivationRequiredTags` 添加 `Game.Playing` → 非 Playing 阶段无法使用能力 +- `ActivationBlockedTags` 添加 `Game.ShowingResult` → 结果显示时禁用能力 +- 阶段观察者:音乐播放、UI 切换、生成逻辑 + +--- + +### 9. 队伍系统 + +> [!note] 新增功能 +> 格斗游戏需要队伍/阵营支持。 + +```cpp +UCLASS() +class URPGTeamSubsystem : public UWorldSubsystem { + void ChangeTeamForActor(AActor* Actor, int32 NewTeamId); + int32 FindTeamFromObject(UObject* Obj) const; + bool CanCauseDamage(AActor* Instigator, AActor* Target) const; + + // 队伍标记栈(跟踪队伍得分等) + void AddTeamTagStack(int32 TeamId, FGameplayTag Tag, int32 Count); + void RemoveTeamTagStack(int32 TeamId, FGameplayTag Tag, int32 Count); + int32 GetTeamTagStackCount(int32 TeamId, FGameplayTag Tag) const; +}; + +// ILyraTeamAgentInterface 实现 +class ILyraTeamAgentInterface : public IGenericTeamAgentInterface { + FOnLyraTeamIndexChangedDelegate OnTeamChanged; +}; +``` + +--- + +## 实施路线图 + +### 阶段 1:基础改造(低风险、高回报) + +| # | 改动 | 来��� | 影响范围 | +|---|------|------|----------| +| 1 | 拆分属性集为 Primary/Combat/Vital/Meta/Progression | Aura | 属性系统 | +| 2 | GameplayTag 输入路由替换 EGSAbilityInputID 枚举 | Lyra | 输入/ASC | +| 3 | 创建 RPGInputConfig DataAsset + RPGInputComponent | Lyra+Aura | 输入 | +| 4 | 实现 AbilitySet DataAsset 模块化能力授予 | Lyra | 能力授予 | + +### 阶段 2:核心改进 + +| # | 改动 | 来源 | 影响范围 | +|---|------|------|----------| +| 5 | 能力激活策略 (OnInputTriggered/WhileInputActive/OnSpawn/OnRhythmBeat) | Lyra | 能力基类 | +| 6 | MMC 派生属性计算(含等级缩放) | Aura | 属性系统 | +| 7 | 激活组系统(格斗游戏攻击取消) | Lyra | ASC | +| 8 | 重构伤害管道(Meta属性 + ExecutionCalc) | Lyra+GASShooter | 伤害 | +| 9 | ClientEffectApplied RPC UI 通知 | Aura | ASC/UI | + +### 阶段 3:架构升级 + +| # | 改动 | 来源 | 影响范围 | +|---|------|------|----------| +| 10 | MVVM WidgetController UI 模式 | Aura | UI | +| 11 | 拆分 LoadingScreen 为独立插件 | 最佳实践 | 插件结构 | +| 12 | GameplayMessageSubsystem 集成(解耦事件) | Lyra | 全局通信 | +| 13 | 装备系统(装备 → AbilitySet → ASC) | Lyra | 装备/物品 | +| 14 | GamePhase 阶段系统(回合管理) | Lyra | 游戏流程 | + +### 阶段 4:高级特性 + +| # | 改动 | 来源 | 影响范围 | +|---|------|------|----------| +| 15 | TagRelationshipMapping 跨能力阻塞/取消 | Lyra | 能力管理 | +| 16 | 组合式能力 Cost 系统 | Lyra | 能力消耗 | +| 17 | 队伍子系统 | Lyra | 队伍/阵营 | +| 18 | GameFeature 模块化扩展 | Lyra | 插件架构 | +| 19 | Save/Load GAS 状态序列化 | 自定义 | 存档 | + +--- + +## MusicFighterGame 特有建议 + +### 节奏输入系统 + +```cpp +// 在 ASC 中添加 +void URPGAbilitySystemComponent::SetCurrentBeatFraction(float BeatFraction) { + // 从 FMOD/AudioAnalysis 获取节拍数据 + CurrentBeatPrecision = CalculateBeatPrecision(BeatFraction); + + if (CurrentBeatPrecision < PerfectThreshold) { + // Perfect 判定 + AddDynamicTagToAllAbilities(RhythmPerfectTag); + } else if (CurrentBeatPrecision < GoodThreshold) { + // Good 判定 + AddDynamicTagToAllAbilities(RhythmGoodTag); + } +} +``` + +### 连招系统建议 + +``` +利用 GameplayTag 层级管理连招状态: +- Combat.Combo.Hit1 → Combat.Combo.Hit2 → Combat.Combo.Hit3 +- 每个连招段使用 EffectContainer Map 的不同 Tag +- 下一段能力需要上一段的 Tag 作为 ActivationRequiredTag +- 节奏加成通过 SetByCaller 修改伤害系数 +``` + +### 乐器/武器即 AbilitySource + +``` +游戏中的乐器(吉他、贝斯、鼓、键盘)作为 Equipment: +- 每个乐器有独立的 AbilitySet +- 不同乐器授予不同的攻击模式和效果 +- 节奏精准度影响伤害倍率 +- 装备管理器处理乐器切换 +``` + +--- + +## 对比总结 + +| 系统 | 当前状态 | 目标状态 | 参考来源 | +|------|----------|----------|----------| +| 输入路由 | 硬编码枚举 | GameplayTag 驱动 | Lyra | +| 属性系统 | 单一 18 属性集 | 5 个分层属性集 + MMC | Aura | +| 能力配置 | CharacterAbilities 数组 | AbilitySet DataAsset | Lyra | +| UI 模式 | 直接 Push | MVVM WidgetController | Aura | +| 伤害计算 | ExecutionCalc + AttributeSet 混用 | 完整 Meta 属性管道 | Lyra+GASShooter | +| 插件模块 | 5 模块混装 | 核心 + 独立 LoadingScreen | 最佳实践 | +| 装备系统 | 无 | 装备 → AbilitySet → ASC | Lyra | +| 阶段管理 | 无 | 层级 Tag GamePhase 子系统 | Lyra | +| 队伍系统 | 无 | TeamSubsystem + TeamAgent | Lyra | +| 消息通信 | 已引入未使用 | GameplayMessageSubsystem 全系统集成 | Lyra | +| 多 Mesh 蒙太奇 | ✅ 已实现 | 保留并优化 | GASShooter | +| EffectContainer | ✅ 已实现 | 保留并扩展类型 | GASShooter | +| RPC 批处理 | ✅ 已实现 | 保留 | GASShooter | + +--- + +## 附录 + +### 参考项目文件索引 + +**LyraStarterGame:** +- `Source/LyraGame/AbilitySystem/LyraAbilitySystemComponent.h` - ASC 标签输入 + 激活组 +- `Source/LyraGame/AbilitySystem/Abilities/LyraGameplayAbility.h` - 能力基类 + 策略 +- `Source/LyraGame/AbilitySystem/LyraAbilitySet.h` - AbilitySet DataAsset +- `Source/LyraGame/AbilitySystem/Phases/LyraGamePhaseSubsystem.h` - 阶段子系统 +- `Source/LyraGame/AbilitySystem/Attributes/LyraHealthSet.h` - 元属性模式 +- `Source/LyraGame/Equipment/LyraEquipmentDefinition.h` - 装备定义 +- `Source/LyraGame/Input/LyraInputConfig.h` - 输入 DataAsset +- `Source/LyraGame/GameFeatures/GameFeatureAction_AddAbilities.h` - 模块化能力授予 +- `Plugins/GameplayMessageRouter/Source/.../GameplayMessageSubsystem.h` - 消息系统 + +**GASShooter:** +- `Source/GASShooter/Characters/Abilities/GSAbilitySystemComponent.h` - 多 Mesh ASC +- `Source/GASShooter/Characters/Abilities/GSGameplayAbility.h` - 能力基类 +- `Source/GASShooter/Characters/Abilities/AttributeSets/GSAttributeSetBase.h` - 属性集 +- `Source/GASShooter/Characters/Abilities/GSDamageExecutionCalc.cpp` - 伤害计算 +- `Source/GASShooter/Characters/Abilities/GSAbilityTypes.h` - EffectContainer +- `Source/GASShooter/Weapons/GSWeapon.h` - 武器系统 +- `Source/GASShooter/Characters/Abilities/GSGATA_Trace.h` - 瞄准系统 + +**UE5_GAS_Aura:** +- `Source/Aura/Public/AbilitySystem/AuraAbilitySystemComponent.h` - Tag 输入 ASC +- `Source/Aura/Public/AbilitySystem/AuraAttributeSet.h` - 三层属性集 + TagsToAttributes +- `Source/Aura/Public/AbilitySystem/Abilities/AuraGameplayAbility.h` - 能力基类 +- `Source/Aura/Public/AbilitySystem/ModMagCalc/MMC_MaxHealth.cpp` - MMC 示例 +- `Source/Aura/Public/Input/AuraInputConfig.h` - 输入 DataAsset +- `Source/Aura/Public/Input/AuraInputComponent.h` - 输入组件模板 +- `Source/Aura/Public/UI/WidgetController/AuraWidgetController.h` - WidgetController 基类 +- `Source/Aura/Public/UI/WidgetController/OverlayWidgetController.cpp` - UI 绑定示例 +- `Source/Aura/Public/UI/WidgetController/AttributeMenuWidgetController.cpp` - 动态属性菜单 +- `Source/Aura/Public/UI/HUD/AuraHUD.h` - HUD 工厂 + +--- + +> 本文档基于 2024-05-30 对三个参考项目的深度代码分析编写。 +> 所有推荐模式均已在对应项目中验证可行。 diff --git a/RPGGameplayAbility重构文档_Sonnet.md b/RPGGameplayAbility重构文档_Sonnet.md new file mode 100644 index 0000000..e0417bd --- /dev/null +++ b/RPGGameplayAbility重构文档_Sonnet.md @@ -0,0 +1,1009 @@ +--- +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) - 重构对象