注册第一条攻击结果
本篇做出最小结算闭环:派生一个可实例化的 UGCS_CombatFlow,在目标角色上把 GGA 的属性 execute 回调转到 HandleGameplayEffectExecute,拼出 FGCS_AttackResult 并 RegisterAttackResult。做完后,Debugger 的 Attack Result 段出现最近一条结果,Default Processor 跑一次。近战窗口和子弹发射不在本篇。
相关文档:运行链路见 战斗流程与攻击结果,Processor 策略见 处理器与战斗钩子。GGA 属性回调见 GGA 文档的属性集与生成器。
前置条件
- 已按 挂上战斗组件 挂好
UGCS_CombatSystemComponent,权威端已InitializeAbilitySystem,Globals 是UGGA_AbilitySystemGlobals。 - 目标 Actor 上有
UGGA_AttributeSystemComponent,并且已授予会经UGGA_AttributeSetEventBridge转发PostGameplayEffectExecute的 AttributeSet。GGA 的UAS_Health/UAS_Combat,以及 GCS 的UAS_Poise,都满足这条。自己写的 AttributeSet 若没有转发,后面的 Flow 永远收不到回调。 - 准备一个瞬时 Gameplay Effect,它必须改某个属性的 Base Value(例如
UAS_Health的 Health 或 IncomingDamage)。只加 Tag、不加 execute 修饰的 Duration Effect 不会进入 PostExecute。 - 准备一行
FGCS_AttackDefinition,TargetEffectClass指向上面的瞬时 GE。
插件不会在属性回调里自动调用 HandleGameplayEffectExecute。Combat 组件只把 Globals 的 PreApply 转给 Flow。PostExecute 要项目自己接到 Flow。
1. 派生 Combat Flow 并放一条 Processor
新建蓝图,父类选 UGCS_CombatFlow(显示名 GCS Combat Flow)。基类是 Abstract,不能填进 CombatFlowClass。
在类默认值的 AttackResultProcessors 里加一条 UGCS_AttackResultProcessor_GameplayEvent 或 UGCS_AttackResultProcessor_GameplayCue:
ExecutePolicy用Default。- Event Processor 填至少一个
EventTriggers;Cue Processor 填至少一个 Cue 标签,或让攻击定义的TargetGameplayCues非空。 - 不要加
UGCS_AttackResultProcessor_Death。它的原生实现是空的,第一次执行只打 Warning。
Processor 必须出现在这个子类的实例上。只改 CDO、却把 CombatFlowClass 指到另一个空子类,列表仍是空的。
把该蓝图填进目标 UGCS_CombatSystemComponent 的 CombatFlowClass。权威端 BeginPlay 会 NewObject 出 Flow 并复制给客户端。
2. 把 GGA 回调转到 Flow
目标 Actor 上,用下面任一入口把 FGGA_GameplayEffectModCallbackData 交给 Flow。两条路都有效,选一条即可。
入口 | 做法 |
|---|---|
蓝图绑定 | 监听 |
项目 AttributeSystem 子类 | 覆写 |
Payload.TargetActor 应是被改属性的那个 Actor。在它上面取 Combat 组件。AttributeSystem 找不到时,EventBridge 静默丢掉转发,Flow 不会收到任何调用。
Instant GE 挂了 UGCS_GEComponent_PredictivelyExecute 时,本地预测 execute 也会进同一条绑定。本篇先用权威端瞬时 GE 验证,不要同时打开预测。
3. 在 Flow 里注册结果
在 Flow 子类覆写 HandleGameplayEffectExecute(蓝图事件同名)。基类实现是空的:只接线、不覆写,容器里仍然没有结果。
最小填写:
- 新建
FGCS_AttackResult。 EffectContextHandle←Payload.ContextHandle。AggregatedSourceTags/AggregatedTargetTags← Payload 里同名容器。OptionalObject本篇留空。- 对所属
UGCS_CombatSystemComponent调用RegisterAttackResult。
RegisterAttackResult 只接受权威端,或 Context 标了预测的本地结果。客户端丢进一条既不权威也不预测的结果会被拒绝并 Warning。
插件不会替你判断“这次 execute 算不算一次攻击”。治疗、回蓝、扣耐力只要走到 PostExecute,也会进这个函数。第一次接入可以先全部注册;正式项目通常用 Get Attack Definition Handle 读 Context,句柄无效就直接返回,避免非战斗 GE 也进容器。
不要在这里再 Apply 一条 GE,也不要手写 HandleAttackResult。RegisterAttackResult 写入 FastArray 后,默认实现会按 Processor 的 ExecutePolicy 分发。
4. 打出一次带攻击上下文的 execute
在权威端对目标 Apply 第 3 步的瞬时 GE。Apply 之前用 UGCS_CombatFunctionLibrary 把攻击定义句柄写入 Effect Context(Set Attack Definition Handle 或 AddAttackHandleToGameplayEffectSpec)。
本篇可以用调试键、关卡脚本或一张只 Apply GE 的测试 Ability。不必先接 Trace 或子弹。命中检测通了但没有 Result,先回到本篇,不要先改通道或动画。
预期结果
权威端 PIE 后,目标 Shared 段能看到 Combat Flow 实例,Combat 段能看到刚才放的 Processor。Apply 一次带攻击句柄的瞬时 GE 后,Attack Result 段出现最近一条结果;LastProcessedAttackResult 能读到同一条。Default Processor 的 Event 或 Cue 各一次。
验证
- Gameplay Debugger 的 Combat 分类:Shared 段 Combat Flow 不是 None;Combat 段 Processor 列表非空。
- Apply 后 Attack Result 段有最近结果,并能看到攻击定义句柄。
- 对 Effect Context 调用
Get Attack Definition Handle,能读回本篇填的行。 LogGCS_Combat提到 Verbose,能看到结算。缺 Flow 时注册会打 Error。- 多人 PIE 先看服务器窗口是否出现 Result。本篇不要用客户端特效证明成功。
常见失败
现象 | 先查 |
|---|---|
Combat Flow 一直是 None | |
AttributeSet 改了,Flow 事件没进 | 目标是否有 AttributeSystem;AttributeSet 是否经 EventBridge 转发;绑定的是不是 |
Flow 事件进了,容器仍空 | 是否覆写了 |
注册被拒绝 | 是否在非权威端、且 Context 不是预测上下文 |
GE 应用了但没有 PostExecute | Effect 是否瞬时且改了 Base Value;Duration 修饰不会进这条回调 |
有 Result,没有 Event / Cue | Processor 是否拖进了这个 Flow 子类; |
治疗或回蓝也进了 Attack Result | 项目没有按攻击定义句柄过滤。这是项目规则,不是插件默认行为 |
加了 Death Processor 角色没死 | 原生实现为空,本篇不要靠它验证闭环 |
下一步
容器里能看到结果之后,再按 做一次近战攻击 或 做一次远程攻击 接命中窗口。要改 Processor 策略或连击钩子,进入 处理器与战斗钩子。