介绍
战斗系统通常涉及到多个方面,如输入绑定,技能激活与否,碰撞判定成功与否,伤害计算正确与否,战斗结果正确与否。
战斗系统相比一般其他的系统,更难以调试和定位问题。
本文介绍常规调试的思路,它不仅仅适用于GCS,也适用于大多数复杂项目。
通过日志调试
[Core.Log]
;Logs for generic input system(针对通用输入系统的日志。)
LogGIPS = Verbose
;Logs for generic gameplay abilities (针对通用技能系统的日志。)
LogGGA_Ability = VeryVerbose
LogGGA_AbilitySystem = VeryVerbose
LogGGA_Tasks = VeryVerbose
;Logs for generic combat system (针对通用战斗系统的日志。)
LogGCS = VeryVerbose
LogGCS_Bullet = VeryVerbose
LogGCS_Trace = VeryVerbose
LogAbilitySystem = VeryVerbose
强烈建议在项目的DefaultEngine.ini中添加如上内容,以开启GCS相关系统的日志。
系统日志会输出系统运行时的大部分细节内容,以帮助你定位问题/排查错误。
通过GameplayDebugger
参考此文档了解如何通过GameplayDebugger对角色当前的Tags,技能等进行调试。
定位问题的流程
每当你认为产生了问题或者Bug时,你可以按照如下思路(从上往下),快速定位到是哪一个方面,从而进行排查。
战斗结果正确与否
若你打中一个人,但没任何效果。
你应该直接在CombatFlow打断点,
若断点执行,那么则可以判定问题出在对战斗结果的处理上(检测AttackResultProcessor的配置,或者检查CombatFlow里的逻辑正确性等)。
如果断点完全没触发,则问题出在下面的某一个流程。
Note
同时你要注意,CombatFlow的回调是通过AttributeSystemComponent转发过来的,你得先确保你有这个组件。
网络预测与结果复制(GCS 1.6)
调试网络战斗时,先区分 GameplayEffect 预测与子弹视觉预测,它们的结算边界不同。
预测 GameplayEffect
如果瞬时 GameplayEffect 配置了 UGCS_GEComponent_PredictivelyExecute,AutonomousProxy 本地应用该效果时会带上 PredictionKey 和 predicting-context 标记,并触发属性回调。可以依次在 AttributeSet 的 PostGameplayEffectExecute、UGCS_CombatFlow::HandleGameplayEffectExecute 和攻击结果注册处检查本地预测路径,再在服务器上检查权威路径及结果复制。
客户端收到权威攻击结果后,会用 PredictionKey 与未消费的本地预测结果匹配。匹配成功会抑制重复的 LocalPredicted 处理;没有匹配到的权威结果仍会按处理器策略执行。核对处理器时确认:
Default跳过 predicting context,用于非预测结果。LocalPredicted处理本地预测结果;未匹配到本地预测的权威结果也会执行。ServerOnly只处理服务器上的非预测权威结果。
子弹预测
子弹只预测玩家主动发射的第一批弹道和视觉表现,预测表现由蓝图实现。预测子弹不会应用 GameplayEffect,也不会触发本地属性回调、预测版攻击结果或 LocalPredicted 处理器。命中与效果结算由服务器权威完成;链式和 Emitter 后续子弹也只由服务器生成。若本地看到弹道但没有伤害,这是预期边界;应在服务器检查 Trace 命中、GameplayEffect 应用及后续 CombatFlow 回调。
伤害计算正确与否
找到你最终要应用的GE上面的MMC/Execution打断点(比如GCS自带的Execution),在里面打断点。GCS中给予目标的GE一般在攻击定义表里配置的。
如果断点触发,那你得检查你的Execution确实给出了有效的数值输出,如果伤害计算没有给对面造成有效的数值修改,或者Execution所参与的某个属性并不存在(检查AttributeSet到底有没有),则后续的流程都不会触发(战斗结果,表现等)。
如果断点完全没触发,则问题出在下面的某一个流程。
碰撞判定成功与否
GCS中与碰撞检测相关的都采用了碰撞追踪系统,你可以查看它的文档了解如何调试/可视化碰撞判定。
如果没打中任何东西,你应该检查子弹/武器/Montage当前所激活/关联的碰撞检测实例,是否采用了正确的TraceDefinition配置。
如果确实有打中东西,则问题出在下面的某一个流程。
输入触发
GIPS有调试指南可以参考,同时你也可以在所引用的InputChecker/Processor蓝图中打断点来判断输入逻辑是否执行。
如果输入确实有执行,则问题出在下面的某一个流程。
否则问题就是在输入这里,检查输入映射配置,以及输入处理的逻辑正确性。
技能的激活与否
这里列出了调试GAS的常规手段。
首先你的确保目标技能到底给了没(打开对应蓝图,检查调试下拉列表有没有该技能实例。)
然后在对应的技能蓝图中打断点,看是否有执行。有执行,那一般就是技能的内部逻辑错误,没有触发后续的流程。
没有执行,那第一步排查的就是技能内部的CanActiveAbility确保没有自定义逻辑在阻断激活。
其次,才到了最难以排查的环节:配置错误。
技能阻挡/取消标签配置多了,乱了,也会阻碍技能的激活。一般这种情况下最好是提升GAS的Log等级,查Log。
很多时候技能的无法激活,都是因为Tags不满足条件造成的。
调试入口
Gameplay Debugger 分段
对着战斗 Actor 打开 Combat 分类。收集顺序覆盖 Shared、Combat、AttackResult、Trace、Bullet、Targeting、Weapon 和 LocalPrediction;LocalPrediction 的结论写进 Shared 的预测摘要。
分段 | 能排除什么 |
|---|---|
Shared | 有没有 DebugActor、Combat / Trace / Bullet / Targeting / Team 组件、战斗实体接口、当前武器;NetRole / NetMode;预测与流水线摘要 |
Combat | Combat Flow 是否实例化、Processor 列表与 ExecutePolicy、连击表、ComboStep、移动标签 |
Attack Result | 最近一条结果、攻击定义、是否预测上下文、PredictionKey 是否匹配复制结果 |
Trace | Handle 数量、激活数、SourceObject / SourceComponent |
Bullet | Entry / 实例、Pending / Confirmed / LocalPredicted 计数 |
Targeting | 当前锁定、Preset、候选目标(候选不复制) |
Weapon | 当前武器名、激活态、标签、Primitive |
LocalPrediction | 本机预测结果是否仍在等待权威匹配;冲突会进 Shared 的 ProblemSummary |
Shared 看不到接口时,先回到 挂上战斗组件,不要查攻击定义。
日志与 Visual Logger
频道 | 看什么 |
|---|---|
| 通用入口和找不到组件/接口 |
| 攻击结算、结果复制、Processor |
| Trace 生命周期和 Sweep |
| Entry、预测确认/否决、命中应用 |
| 锁定、候选刷新、Selection Task |
源码用 GCS_VLOG_* / GCS_VLOG_UELOG_* 把高频决策写进 Visual Logger。关键事件会同时打输出日志。把对应频道提到 Verbose,再在 Visual Logger 里按 Actor 过滤。
编辑器开关
UGCS_DeveloperSettings.bDisableAffiliationCheck:关掉阵营过滤,用来确认“打不到队友”是不是 Affiliation Filter。这是调试开关,不要留在发行配置。- Processor 的
bEditorDebugEnabled:编辑器里可以单条关掉 Processor,用来判断是 Cue、Gameplay Event 还是项目死亡逻辑没跑。
症状到原因
症状 | 先看 | 常见原因 |
|---|---|---|
蓝图或 Debugger 找不到组件 | Shared 组件勾选 | 插件未编译;组件没挂;查错了 Actor |
有动画无命中 | Trace 段 Handle / 激活 | 只配了 |
GE 没有攻击上下文 | Attack Result 的定义句柄; | 没用 |
预测与权威重复结算 | Attack Result 的匹配标记;Processor Policy | LocalPredicted Processor 在已匹配的复制结果上又跑了一次;或权威逻辑放进了 LocalPredicted |
子弹有轨迹无 GE | Bullet 段 Pending / LocalPredicted | 预测弹按契约不应用 GE。服务器 Entry 未确认时这是正常现象 |
阵营误伤或打不到任何人 | Targeting / Team;Developer Settings | Affiliation Filter 在生效,或 |
Combat Flow 为 None | Shared / Combat | |
Death Processor 没死人 | Combat 段 Processor | |