总览
GAS 出问题时,表象经常很像:“技能按了没反应”“Buff 不生效”“伤害不扣”“Cue 没播”。但根因可能在输入、Spec、ActorInfo、Tag、Cost、Cooldown、PredictionKey、TargetData、Attribute 复制、Cue 路径或服务器 Authority。
本篇整理一套调试顺序,并补充 UE5.8 的实验性 GASToolsets 能帮什么。
源码依据
关键来源:
GameplayAbilities/README.mdAbilitySystemComponent.hAbilitySystemComponent_Abilities.cppEngine/Plugins/Experimental/Toolsets/GASToolsets
UE5.8 GAS README 里强调 Gameplay Debugger 是首选调试方式,旧的 ShowDebug AbilitySystem 更偏遗留。README 还列出了一组控制台命令,用于授予、激活、取消 Ability,查看和应用 GE。
先判断是哪台机器的问题
多人 GAS 调试第一步不是看代码,而是确认问题发生在哪台机器:
| 现象 | 可能位置 |
|---|---|
| 本地按键没反应 | 输入层、客户端 ASC、Ability Tag |
| 本地有表现但服务器没伤害 | TargetData、Prediction、Authority |
| 服务器有伤害但客户端 UI 不变 | Attribute RepNotify、UI 绑定 |
| 自己能看到 Cue,别人看不到 | Cue 复制、网络相关性 |
| Ability 激活一次后再也不能用 | EndAbility、ActiveCount、Cooldown |
先把机器边界分清,能少走很多弯路。
Ability 激活失败排查
按这个顺序查:
- 输入是否到达 Ability 输入组件。
- 输入 Tag 是否正确。
- ASC 是否有效。
InitAbilityActorInfo是否在客户端和服务器都执行。- Ability 是否已
GiveAbility。 - Spec Handle 是否有效。
- Net Execution Policy 是否允许当前机器激活。
- Cost 是否足够。
- Cooldown Tag 是否存在。
- Required/Blocked Tags 是否阻止。
CanActivateAbility是否返回 false。
控制台命令可以辅助:
AbilitySystem.Ability.ListGranted
AbilitySystem.Ability.Activate
AbilitySystem.Ability.Cancel
AbilitySystem.Ability.Grant
如果 ListGranted 里没有 Ability,就别继续查输入了,先查服务器授予。
GameplayEffect 排查
GE 不生效时,按顺序看:
- GE Spec 是否创建成功。
- 目标 ASC 是否正确。
CanApply和 Application Query 是否通过。- Modifier 属性是否有效。
- Duration Policy 是否符合预期。
- 是否被 Immunity 阻止。
- 是否进入 ActiveGameplayEffects。
- Instant GE 是否执行了 PostGameplayEffectExecute。
- Stack 是否被合并或拒绝。
- Cue 是否被触发。
命令:
AbilitySystem.Effect.ListActive
AbilitySystem.Effect.Apply
AbilitySystem.Effect.Remove
建议项目日志记录 GE 应用结果:Source、Target、GE Class、PredictionKey、Authority、Duration、StackCount、失败原因。
Attribute 排查
属性异常通常来自三个地方:
- GE 没有真正修改属性。
- AttributeSet 回调把值 clamp 或覆盖了。
- 复制/UI 对账没触发。
检查点:
| 检查 | 说明 |
|---|---|
| 属性宏 | 是否有 ATTRIBUTE_ACCESSORS |
| 复制 | 是否 ReplicatedUsing |
| RepNotify | 是否 REPNOTIFY_Always |
| OnRep | 是否调用 GAMEPLAYATTRIBUTE_REPNOTIFY |
| Clamp | PreAttributeChange 是否把值改掉 |
| Meta | Damage 是否在 PostExecute 被消费 |
如果服务器 Health 已经变了,客户端 UI 没变,优先看 RepNotify 和 UI 绑定。
Cue 排查
Cue 没播时:
- Cue Tag 是否正确。
- Cue Notify 是否存在。
- Cue 路径是否被扫描。
- GE 是否带了 Cue。
- Cue Event 是否匹配 Notify 方法。
- Cue 参数 Location 是否有效。
- 目标 Actor 是否 relevant。
- PlayerState ASC 是否需要复制代理。
不要第一时间怪 Niagara。先确认 Cue 事件到底有没有到 Notify。
Visual Logger
Visual Logger 很适合记录时间线:
- Ability 激活和结束。
- GE 应用和移除。
- TargetData 验证。
- 伤害原始值和最终值。
- Tag 添加和移除。
- 服务器拒绝原因。
项目可以封装一组 GAS 日志宏,让每次关键路径都能写到 Visual Logger。多人问题最怕“当时到底发生了什么”没有证据。
UE5.8 GASToolsets
UE5.8 新增的实验性 GASToolsets 在:
Engine/Plugins/Experimental/Toolsets/GASToolsets
它是 EditorOnly、Experimental、默认关闭,依赖 GameplayAbilities 和 ToolsetRegistry。它分三组:
| Toolset | 能力 |
|---|---|
UAttributeSetToolset |
查找 AttributeSet 类、列出属性 |
UAbilitySystemInspectorToolset |
获取 Attribute Values、Active Effects、Granted Abilities、Active Tags |
UGameplayCueToolset |
列出 Cue、获取 Cue 信息、执行 Cue、查找/创建 Cue Notify、添加/移除 Cue Tag |
它适合 AI Assistant 或 MCP 场景下排查“选中 Actor 当前 GAS 状态”。但创建 Cue Notify、添加或删除 Cue Tag 这类修改项目内容的工具,源码里也有需要明确授权的提示。团队流程里应该要求人工确认和版本控制。
项目落地调试面板
即使不用 GASToolsets,项目也建议做一个内部调试面板:
| 面板 | 内容 |
|---|---|
| Abilities | Granted、Active、InputTag、Cooldown |
| Effects | Active GE、Duration、Stack、Granted Tags |
| Attributes | Health、Mana、MoveSpeed 等关键属性 |
| Tags | Owned Tags、Loose Tags、Blocked Tags |
| Prediction | 当前 PredictionKey、是否本地预测 |
| TargetData | 最近一次目标数据、服务器校验结果 |
| Cue | 最近触发 Cue 和参数 |
这个面板在多人联调时非常值钱,比只看日志更直观。
常见失败剧本
| 现象 | 优先检查 |
|---|---|
| 技能完全没反应 | 输入 Tag、Spec 是否存在、ActorInfo 是否初始化 |
| 技能本地播了但服务器没效果 | Net Policy、PredictionKey、TargetData RPC |
| 伤害为 0 | SetByCaller Tag、Execution 捕获、Armor 公式 |
| UI 血量不变 | Attribute RepNotify、UI 委托绑定 |
| Buff 图标不消失 | Active GE 移除、Duration、Stack |
| Cue 不显示 | Cue Tag、Notify 路径、网络相关性 |
| 冷却一直卡住 | Cooldown GE 是否移除、Tag 是否残留 |
常见坑
- 只看客户端日志。 多人问题必须看服务器。
- 没有失败原因 Tag。 OptionalRelevantTags 可以帮助 UI 和日志说明失败原因。
- 调试命令没接生产数据。 控制台 Apply GE 要用真实 GE 和真实目标测试。
- 不记录 PredictionKey。 预测问题会很难复盘。
- AI Toolset 直接修改资产。 自动创建/删除 Cue 前必须人工确认。
本篇结论:GAS 调试要按链路查,不要凭感觉猜。输入、Spec、ActorInfo、Tag、Cost、GE、Attribute、Cue、Prediction、TargetData,每一层都有可观察状态。把这些状态暴露出来,GAS 就没那么神秘。
源码路径索引
Engine/Plugins/Runtime/GameplayAbilities/Source/GameplayAbilities/Public/AbilitySystemComponent.hEngine/Plugins/Runtime/GameplayAbilities/Source/GameplayAbilities/Private/AbilitySystemComponent.cppEngine/Plugins/Runtime/GameplayAbilities/Source/GameplayAbilities/Private/AbilitySystemComponent_Abilities.cppEngine/Plugins/Runtime/GameplayAbilities/Source/GameplayAbilities/Public/Abilities/GameplayAbility.hEngine/Plugins/Runtime/GameplayAbilities/Source/GameplayAbilities/Public/GameplayEffect.hEngine/Plugins/Runtime/GameplayAbilities/Source/GameplayAbilities/Public/AttributeSet.hEngine/Plugins/Runtime/GameplayAbilities/Source/GameplayAbilities/Public/GameplayPrediction.h