GAS 系统深度学习指南UE 5.4 / 5.5

12 网络同步与复制(Replication)

目标:建立"GAS 里什么数据走哪条网络通道"的完整地图——复制模式、同步矩阵(已修正)、Ability 复制、带宽优化。


12.1 GAS 的网络模型

GAS 采用服务端权威(Server Authority)模型:所有伤害、属性修改、能力激活的最终判定都在服务端。客户端(拥有者)通过预测获得手感,通过复制获得状态。

要正确使用 GAS 多人功能,必须清晰回答四个问题:

  1. 谁的 ASC 复制什么数据?(复制模式)
  2. 能力是怎么同步的?(RPC + 复制)
  3. 属性/效果/标签/表现各自走哪条通道?
  4. 怎么控制带宽?

12.2 复制模式(ReplicationMode)总览

enum class EGameplayEffectReplicationMode
{
    Minimal,   // AI/大量单位
    Mixed,     // 玩家角色(Fortnite 默认)
    Full,      // 单机/极小规模
};

同步矩阵(已按权威文档修正)

数据类型 Full Mixed Minimal
GameplayEffect 所有客户端 仅拥有者客户端 不复制给任何人
GameplayTag(GE 授予) 所有客户端 随 GE(拥有者客户端)* 不复制
GameplayTag(Loose) 不复制(本地) 不复制(本地) 不复制(本地)
GameplayCue 所有客户端(不可靠多播) 所有客户端(不可靠多播) 所有客户端(不可靠多播)
AttributeSet 属性 所有客户端 仅拥有者客户端 不复制

* 关于 Mixed 下"Tag 复制给所有客户端"的准确口径:GE 复制范围决定 Tag 复制范围——Mixed 下 GE 只到拥有者客户端,因此非拥有者客户端看不到别人身上的 GE 授予 Tag。旧资料里"Mixed 下 Tag 同步给所有客户端"的表格表述过于笼统,实际取决于 Tag 由哪种机制授予。

三条铁律(再次强调):

  1. GameplayCue 在所有模式下都不可靠多播到所有客户端——唯一的"全员可见"表现通道;
  2. Mixed 模式要求 OwnerActor 的 Owner 是 Controller(PlayerState 天然满足;Character 需手动设置);
  3. Fortnite 实战:玩家角色 Mixed、AI 单位 Minimal,这是社区推荐的默认配置。

12.3 能力(GameplayAbility)怎么同步

关键事实:

  • Ability 的逻辑不会在模拟代理上运行。Simulated Proxy 只通过表现通道(动画、Cue)"假装"看到技能,真正的 Ability 实例只在服务端和拥有者客户端存在;
  • Ability 的复制:ReplicationPolicy = Replicate 且设置了实例化策略的 GA 类,其 Spec 会复制给客户端。这样客户端能拿到"这个角色有哪些技能"(用于 UI、输入绑定),但技能执行仍走服务端;
  • 激活/结束的同步:通过 RPC 完成——ServerTryActivateAbility(客户端→服务端)、ClientActivateAbilitySucceed/Failed(服务端→客户端)、ServerEndAbility / ClientEndAbility;
  • 同帧快速技能可批处理:一个"激活 + 发送 TargetData + 立即结束"的技能,GAS 会把这几个 RPC 合并成一个(Ability Batching),减少网络包数。

12.4 效果(GameplayEffect)的复制机制

  • Duration/Infinite GE 生成 FActiveGameplayEffect 存入 FActiveGameplayEffectsContainer(FFastArraySerializer),逐条复制;
  • Instant GE 不进入该容器:它只在服务端执行(改 BaseValue),然后通过属性复制把结果值同步给客户端——所以客户端看到的是"属性值变化",而不是"Instant GE 本身";
  • GE 的复制模式就是 ASC 的 ReplicationMode;
  • 预测性施加的 GE:带预测键,客户端本地先有,服务端确认后覆盖。

12.5 属性(AttributeSet)的复制

  • 属性通过 DOREPLIFETIME_CONDITION_NOTIFY 注册复制(第 04 章);
  • 复制范围取决于 ReplicationMode:Mixed 下仅拥有者客户端能看到自己的属性值;其他玩家看到对方的 HP 通常是通过 GameplayCue / UI 事件(比如命中后飘字),而不是直接读对方属性;
  • 属性复制走的是整块属性更新(值变化即同步),实时性足够,但要避免高频无意义变化(如每帧变化的临时值)。

12.6 标签(GameplayTag)的复制

授予方式 复制行为
GE 的 Granted Tags 随 GE 复制(见同步矩阵)
Ability 的 Activation Owned Tags 不复制(本地)
Loose GameplayTags 不复制;UE5 ReplicatedLooseGameplayTags 仅复制给拥有者客户端(COND_ReplayOrOwner)
Fast Replication(项目设置) 用位掩码压缩高频复制标签,需要两端标签列表一致

设计结论:需要"所有客户端都看到的状态"(如死亡、眩晕),优先用 GameplayCue 让各端自行表现;需要"只有自己和服务端知道"的状态用 GE Granted Tags 或 Loose Tag。别指望 Loose Tag 广播给所有人。

12.7 同步架构选择

ASC 放哪(回顾)

放置 优点 缺点 适用
Character 简单 死亡丢失数据 单机原型
PlayerState 数据持久 依赖 PlayerState 复制 玩家角色(推荐)
自定义 Component 灵活(Lyra) 复杂 大型项目

网络拓扑

拓扑 说明
Listen Server 主机兼服务端,主机本机延迟 0;Cue 可能双触发
Dedicated Server 独立服务端,无本地玩家,最干净
单机 无网络开销,但仍可开启复制做架构一致

12.8 带宽优化清单

  1. AI 用 Minimal 复制模式——AI 的 GE/属性根本不复制,省大量带宽;
  2. 慎用 Full 模式——Full 会把每个 GE 复制给所有客户端,只在极小规模使用;
  3. GameplayCue 走不可靠通道——可丢失,别承载关键逻辑;
  4. 启用 Fast Replication(项目设置 → GameplayTags)压缩高频标签;
  5. 属性按需复制——Meta 属性、纯服务端属性不注册复制;
  6. 合并同帧 RPC(Ability Batching)减少包数;
  7. 慎用 Full 的 Full——即"所有 GE 复制给所有人",加上不可靠 Cue 高频触发,容易打满带宽。

大规模优化:属性代理复制(Fortnite 大逃杀方案)

100 人大厅中,每个玩家的 ASC 在 PlayerState(always-relevant)上,直接复制大量属性带宽爆炸。Fortnite 的方案:

// 概念代码:模拟代理跳过 ASC 直接复制
void AFortnitePlayerState::ReplicateSubobjects(...)
{
    if (bIsSimulatedProxy) return;   // 不复制 ASC
    Super::ReplicateSubobjects(...);
}

// Pawn 上的代理结构体(位掩码压缩白名单标签)
USTRUCT()
struct FAttributeProxy
{
    GENERATED_BODY()
    UPROPERTY(Replicated) float Health;
    UPROPERTY(Replicated) float Shield;
    UPROPERTY(Replicated) float MaxHealth;
    UPROPERTY(Replicated) uint32 TagBitmask;
};
  1. 模拟代理上禁用 ASC 直接复制;
  2. 用代理结构体在 Pawn 上复制属性子集;
  3. 客户端收到代理数据后推送到本地 ASC。

Dave Ratti 评价:"不确定在 Replication Graph 等优化后是否仍必要,且不是最可维护的模式。"大型项目优先考虑 Replication Graph,而非手工代理复制。

大规模优化:ASC 懒加载(Fortnite 方案)

大量可破坏 Actor(树木、建筑)每个都挂 ASC 成本高。FNBR 优化为只在首次受伤时创建 ASC:

void AMyDamageableActor::TakeDamage(float Damage, ...)
{
    if (!AbilitySystemComponent)   // 首次受伤才创建
    {
        AbilitySystemComponent = NewObject<UAbilitySystemComponent>(this);
        AbilitySystemComponent->RegisterComponent();
        // 初始化属性集等
    }
    // 应用伤害 GE
}

12.9 调试工具

showdebug abilitysystem          # 屏幕调试视图(标签/能力/效果)
AbilitySystem.Debug.NextCategory # 切换调试类别
AbilitySystem.Debug.NextTarget   # 切换调试目标
AbilitySystem.Debug.ClearAll     # 清除调试
Log AbilitySystem Verbose        # 详细日志
stat game                        # 网络统计
net showcorrections              # 属性校正

旧资料中的 AbilitySystem.Debug.Category.Prediction、net.PredictionKey.MaxDelay 等命令并不存在,请使用上面的真实命令。

12.10 本章验证

  • [ ] 配置 PlayerState 承载 ASC + Mixed 模式,双人联机验证"自己能看到自己属性,看不到对方属性细节";
  • [ ] 用 Minimal 模式跑 AI 单位,对比带宽(stat game / 网络分析器);
  • [ ] 联机验证 Cue 在所有模式下都多播到所有客户端;
  • [ ] 用 showdebug abilitysystem 检查自己与对方 ASC 的标签/能力状态。

下一章:13 实战:从零构建一个技能角色