UE5.8 Gameplay Ability System 专题系列

UE5.8 GAS 专题(八):预测、复制与服务器权威

围绕 PredictionKey、FScopedPredictionWindow、Net Execution Policy、ReplicationMode、RPC 批处理和预测失败回滚,拆解 GAS 多人同步核心。

总览

GAS 真正值钱的地方之一是多人预测。玩家按下翻滚或开火时,本地立刻有反馈;服务器仍然保留权威,确认成功或拒绝后再对账。这个能力让手感和反作弊之间有了工程上的折中。

本篇讲 PredictionKeyFScopedPredictionWindow、Net Execution Policy、ReplicationMode、RPC 批处理和“哪些东西不能预测”。

UE5.8 GAS 专题(八):预测、复制与服务器权威 配图
LocalPredicted Ability 先在拥有客户端执行,再由服务器确认或拒绝;PredictionKey 负责对账。

源码依据

关键文件:

  • GameplayPrediction.h
  • AbilitySystemComponent_Abilities.cpp
  • AbilitySystemComponent.h
  • GameplayAbilityTypes.h

GameplayPrediction.h 注释把边界写得很清楚。GAS 可以预测:

  • 初始 Ability 激活。
  • 触发事件。
  • GE 对属性和标签的修改,但不包括复杂 Execution 结果。
  • GameplayCue。
  • Montage。
  • 部分移动。

GAS 不预测:

  • GameplayEffect 移除。
  • Periodic GameplayEffect。
  • 一些复杂服务器权威结果。

PredictionKey 是什么

PredictionKey 是客户端和服务器对账的票据。LocalPredicted Ability 激活时,客户端创建 PredictionKey,本地先执行副作用,同时把激活请求发给服务器。服务器接受后,复制权威结果;服务器拒绝后,客户端回滚预测副作用。

流程:

  1. 客户端 TryActivateAbility
  2. 创建 FScopedPredictionWindow
  3. 发送 ServerTryActivateAbility,携带 PredictionKey。
  4. 客户端立即 ActivateAbility
  5. 服务器检查 Cost、Cooldown、Tag、Authority、目标合法性。
  6. 服务器接受或拒绝。
  7. 客户端按复制结果对账。

PredictionKey 只对发起客户端有意义。其他客户端看到的是服务器权威复制结果。

Prediction Window 的边界

预测窗口通常只覆盖初始调用栈。也就是说,在 ActivateAbility 里立即应用的 GE、Cue、Montage 可以共享这次 PredictionKey;但如果你开了一个计时器,或者等待输入释放,后续回调已经离开初始窗口。

后续阶段如果还要发送预测事件,需要新的 FScopedPredictionWindow

void UGA_ChargeShot::HandleInputReleased(float HoldSeconds)
{
    UAbilitySystemComponent* ASC = GetAbilitySystemComponentFromActorInfo();
    if (!ASC)
    {
        return;
    }

    FScopedPredictionWindow PredictionWindow(ASC, true);

    SendTargetDataAndApplyPredictedCue(HoldSeconds);
}

没有新的预测窗口,客户端以为自己提交了数据,服务器却无法正确关联预测副作用。

Net Execution Policy

策略 行为 用法
LocalPredicted 客户端先执行,服务器确认 翻滚、开火、近战起手
LocalOnly 只在本地执行 UI 和本地辅助
ServerInitiated 服务器发起,客户端可表现 AI 技能、服务器事件
ServerOnly 只在服务器执行 权威管理、敏感结算

不要把所有 Ability 都设为 LocalPredicted。只有手感强、可以接受预测失败回滚的行为才适合预测。购买、掉落、任务提交、排行榜结算这些应该 ServerOnly。

ReplicationMode 与可见性

ASC 的 ReplicationMode 决定 Active GE 细节如何复制:

模式 拥有者 非拥有者
Full 完整 完整
Mixed 完整 精简
Minimal 精简 精简

玩家常用 Mixed。拥有者需要 UI、冷却、Buff 细节;其他客户端多数只需要 Cue 和状态 Tag。AI 大量存在时用 Minimal 减少网络压力。

RPC 批处理

GAS 支持把 Ability 激活、TargetData、End 等 RPC 批在一起,源码 README 提到 FScopedServerAbilityRPCBatcherShouldDoServerAbilityRPCBatch。这适合“按下开火后立即发送目标数据并结束”的短 Ability。

批处理适合:

  • Hitscan 武器。
  • 单次近战命中。
  • 快速交互。

不适合:

  • 长时间引导。
  • 多段 Combo。
  • 需要多次 TargetData 的复杂技能。

使用前要测高延迟和丢包,不要只看本地 Listen Server。

属性预测对账

预测 Instant GE 时,源码会把它临时当成 Infinite delta,等服务器结果回来后移除预测副本。Attribute 复制必须用:

  • DOREPLIFETIME_CONDITION_NOTIFY(..., REPNOTIFY_Always)
  • GAMEPLAYATTRIBUTE_REPNOTIFY

否则客户端可能收到了服务器值,但 RepNotify 没触发,UI 或属性聚合没对上。

项目落地测试清单

每个 LocalPredicted Ability 至少测试:

  1. 0 延迟。
  2. 100ms 延迟。
  3. 200ms 延迟。
  4. 服务器拒绝激活。
  5. Cost 不足。
  6. Cooldown 未结束。
  7. 目标无效。
  8. 角色死亡时激活。
  9. 激活中断线重连。
  10. 远端玩家是否看到正确 Cue。

如果某个技能在 0 延迟看起来没问题,但高延迟下重复播 Cue、UI 闪回、伤害出现两次,说明预测副作用和服务器对账没有设计好。

常见坑

  • 所有技能都 LocalPredicted。 敏感结算会变得难控制。
  • 离开预测窗口后继续当成本地预测。 异步回调需要新的 PredictionWindow。
  • 预测周期 GE。 源码明确不预测 Periodic。
  • 预测 GE 移除。 移除由服务器权威复制。
  • 属性 RepNotify 写错。 UI 和预测对账会出问题。
  • 只测 Listen Server。 Dedicated Server 和网络模拟必须测。

本篇结论:预测不是“客户端也跑一遍”这么简单,而是一套有票据、有窗口、有边界的对账机制。把不能预测的内容留给服务器,把能预测的表现做好回滚,GAS 多人体验才会稳定。

源码路径索引

  • Engine/Plugins/Runtime/GameplayAbilities/Source/GameplayAbilities/Public/AbilitySystemComponent.h
  • Engine/Plugins/Runtime/GameplayAbilities/Source/GameplayAbilities/Private/AbilitySystemComponent.cpp
  • Engine/Plugins/Runtime/GameplayAbilities/Source/GameplayAbilities/Private/AbilitySystemComponent_Abilities.cpp
  • Engine/Plugins/Runtime/GameplayAbilities/Source/GameplayAbilities/Public/Abilities/GameplayAbility.h
  • Engine/Plugins/Runtime/GameplayAbilities/Source/GameplayAbilities/Public/GameplayEffect.h
  • Engine/Plugins/Runtime/GameplayAbilities/Source/GameplayAbilities/Public/AttributeSet.h
  • Engine/Plugins/Runtime/GameplayAbilities/Source/GameplayAbilities/Public/GameplayPrediction.h