--- 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 对三个参考项目的深度代码分析编写。 > 所有推荐模式均已在对应项目中验证可行。