网络复制与 RPC
Network Replication & RPC
UE 采用服务器权威 (Server-Authoritative) 的客户端-服务器模型:游戏真正在服务器上进行,服务器把状态复制 (Replication) 给客户端,客户端通过远程过程调用 (Remote Procedure Call, RPC) 向服务器请求操作。开发者需要显式声明哪些 Actor、属性、函数要走网络,并借助所有权、网络角色、相关性、优先级控制“发给谁、发多少”。UE 5.8 提供通用复制系统、Replication Graph 和实验性的 Iris 三套复制系统。
网络模型与网络模式
服务器持有唯一真实的权威游戏状态;每个客户端控制自己在服务器上拥有的 Pawn,把操作以 RPC 发往服务器,服务器再把 Actor 位置、行为、变量值复制给各客户端,客户端据此模拟一个近似的服务器世界。服务器默认不推流画面,而是发送状态让客户端自行渲染。(Networking Overview)
| 网络模式 | ENetMode | 说明 |
|---|---|---|
| 单机 Standalone | NM_Standalone | 也被视为服务器,但不接受远程连接;同时跑服务器与客户端逻辑 |
| 专用服务器 Dedicated Server | NM_DedicatedServer | 无本地玩家,丢弃图形/声音/输入;公平、高效,适合 MMO、竞技 MOBA、快节奏射击 |
| 监听服务器 Listen Server | NM_ListenServer | 主机同时是玩家;易搭建,但主机有优势且负载更高,适合休闲合作/对抗 |
| 客户端 Client | NM_Client | 不运行任何服务器端逻辑 |
因为单机模式本身就是“服务器 + 客户端”,按多人方式写的逻辑在单机下无需额外工作即可运行。官方强烈建议:只要项目将来可能做多人,从一开始就按多人写,事后改造需要通读并重写大量玩法代码。(Networking Overview)
复制的对象:Actor 是基本单位
AActor 是 UObject 继承链上第一个支持网络的类;普通 UObject 只能作为挂在 Actor 上的复制子对象复制。大多数 Actor 默认不复制,要设置 bReplicates = true(蓝图里勾 Replicates)。开启后自动处理的只有创建/销毁(服务器生成权威 Actor 后在客户端生成远程代理)和可选的移动复制(bReplicateMovement:位置、旋转、速度);属性、函数、组件、子对象都要手动声明。(Networking Overview)
以下不复制、各客户端独立运行:骨骼/静态网格组件、材质、动画蓝图、粒子组件、音源、物理对象。正确做法是复制驱动它们的变量,让各端以相近方式模拟——例如复制一个“正在瞄准”布尔量,而不是复制动画。(Networking Overview)这与 Gameplay 框架 中 GameMode 只存在于服务器、GameState/PlayerState 负责向客户端同步状态的分工相互印证。
属性复制与 RepNotify
声明步骤:UPROPERTY(Replicated) 或 UPROPERTY(ReplicatedUsing=OnRep_X) → 构造中 bReplicates = true → 重写 GetLifetimeReplicatedProps 并调用 DOREPLIFETIME(需 #include "Net/UnrealNetwork.h")。这些说明符依赖反射系统,见 UObject 与反射系统。(Replicate Actor Properties)
- 只有值变化才复制,未变化的属性不占带宽。属性一旦注册就在对象整个生命周期内复制、不能注销——系统借此在多个连接间共享计算。(Replicate Actor Properties)
- RepNotify:属性在客户端被复制更新时调用
OnRep_函数;函数可带一个同类型参数,系统会传入旧值。REPNOTIFY_Always每次复制都回调,REPNOTIFY_OnChanged仅值改变时回调。(Replicate Actor Properties) - C++ 与蓝图差异:蓝图里对复制属性用 Set 节点会自动调用 RepNotify(按引用修改的宏/函数一般不会);C++ 中 RepNotify 只在客户端收到复制时调用。(Replicate Actor Properties)
NotReplicated用于在复制结构体中排除某个成员。
常用复制条件(DOREPLIFETIME_CONDITION):
| 条件 | 含义 |
|---|---|
COND_InitialOnly | 只在初始数据包中尝试复制 |
COND_OwnerOnly | 只发给 Actor 的所有者 |
COND_SkipOwner | 发给除所有者外的所有连接 |
COND_SimulatedOnly / COND_AutonomousOnly | 只发给模拟代理 / 自主代理 |
COND_Custom | 配合 PreReplication 中的 DOREPLIFETIME_ACTIVE_OVERRIDE 开关 |
COND_Dynamic / COND_Never | 运行时改条件 / 从不复制 |
自定义条件按 Actor 而非按连接判断,因此不能依赖随连接变化的状态,且比预置条件更耗 CPU;_FAST 宏在编译期构建描述符以省 CPU。(Replicate Actor Properties)
对象引用以服务器分配的 FNetworkGUID 传输。能被网络引用的对象:复制的 Actor/组件、“稳定命名”的非复制 Actor/组件(从包加载、非运行时生成;构造函数里添加的组件可用 SetNetAddressable 标记)、已加载包里的非 Actor 非组件 UObject。(Replicate Actor Properties)
RPC:类型、执行位置与可靠性
RPC 本地调用、远端执行,单向、不能有返回值;官方定位的主要用途是瞬时或表现类事件(音效、粒子、动画)。声明形如 UFUNCTION(Server, Reliable) void ServerFire();,实现写在 ServerFire_Implementation;约定以 Server/Client/Multicast 作函数名前缀。(Remote Procedure Calls)
| 类型 | 在哪执行 | 关键规则 |
|---|---|---|
Server | 服务器 | 必须由拥有该 Actor 的客户端调用,否则被丢弃 |
Client | 该 Actor 的所属客户端 | 服务器上调用、Actor 无所有者时在服务器本地执行 |
NetMulticast | 服务器 + 所有该 Actor 相关的客户端 | 从客户端调用只在本地执行 |
Remote | 连接的远端 | 永不在本地执行;未暴露给蓝图 |
下图展示一次“客户端开火”在网络上的典型路径:客户端向服务器发 Server RPC,服务器做权威判定并生成投射物(自动复制给所有客户端),表现用多播或 RepNotify 广播。
sequenceDiagram participant C1 as 客户端 1(自主代理) participant S as 服务器(权威) participant C2 as 客户端 2(模拟代理) C1->>S: ServerFire()(Server RPC,需由所属客户端调用) S->>S: 校验 _Validate / 生成投射物 S-->>C1: 复制投射物 Actor 与属性 S-->>C2: 复制投射物 Actor 与属性 S-->>C2: MulticastFireFX()(不可靠多播,表现)
图中实线为 RPC 请求,虚线为服务器下发的复制数据;对应官方网络概览中“玩家 1 开火”的逐步对照。(Networking Overview)
可靠性:RPC 默认不可靠(丢包即丢弃、无序)。Reliable 会重发直至确认,且后续 RPC 会被挂起直到它被确认,保证有序但更耗带宽。WithValidation 为 Server RPC 增加 _Validate,返回 false 时断开调用客户端——“信任但验证”。(Remote Procedure Calls)
所有权与网络角色
- 所有者与所属连接 (Owner & Owning Connection):客户端连入时服务器为它创建 PlayerController,PC 占有 (Possess) 并拥有 Pawn;Actor 的所属连接就是其最外层所有者 PlayerController 的连接,组件沿 Outer 链找到所属 Actor。所属连接决定:
bOnlyRelevantToOwner的相关性(PlayerController 默认只对自己的所有者相关)、基于所有者的复制条件、Client RPC 的投递目标。Pawn 只在被占有期间属于该连接。(Actor Role/Remote Role & Owner/Owning Connection) - 网络角色 (Net Role):
GetLocalRole()/GetRemoteRole(),与所有权不是一回事。
| 本地角色 | 远程角色 | 观察端 | 含义 |
|---|---|---|---|
ROLE_Authority | ROLE_AutonomousProxy | 服务器 | 某客户端控制的 Pawn |
ROLE_AutonomousProxy | ROLE_Authority | 客户端 | 本客户端控制的 Pawn |
ROLE_SimulatedProxy | ROLE_Authority | 客户端 | 其他玩家的 Pawn 或无人控制的复制 Actor |
ROLE_Authority | ROLE_None | 客户端 | 非复制的本地 Actor |
只有服务器应在复制 Actor 上看到 ROLE_Authority。服务器按 NetUpdateFrequency 频率而非每帧复制,客户端在两次更新之间模拟角色移动以免卡顿。(Actor Role/Remote Role & Owner/Owning Connection)
相关性与优先级:带宽怎么分
- 相关性 (Relevancy):按连接判断 Actor 是否“可能对该客户端产生显著影响”,只复制相关的 Actor;动态生成的复制 Actor 不再相关时会在客户端被销毁。
AActor::IsNetRelevantFor依次判断:总是相关、属于该连接的 Pawn/PC、是该 Pawn、是动作发起者 → 相关;bNetUseOwnerRelevancy时跟随所有者;隐藏且无碰撞根组件 → 不相关;启用距离相关性时在NetCullDistanceSquared内 → 相关。(Actor Relevancy) - 优先级 (Priority):带宽饱和时按优先级分配,
NetPriority只有比值有意义,全体放大没有用。默认 Actor 1.0、Pawn 3.0、PlayerController 3.0;GetNetPriority再按距离、视线和距上次复制的时间乘以系数(如 0.2、0.4、2.0,阈值见NetworkingDistanceConstants.h)。(Actor Priority)
这种“按观察者距离/视野决定更新多少”的思路与渲染中的 细节层次 同源;MassEntity 数据导向框架 的 Replication LOD 也是按每个观察者计算复制相关性。
三套复制系统与 Iris
| 系统 | 定位 | 主要特性 |
|---|---|---|
| 通用复制系统 (Generic) | 当前默认 | 休眠 (Dormancy)、优先级、相关性 |
| Replication Graph | 插件 | 面向大量复制 Actor 的可扩展性 |
| Iris | 最新、实验性,可选启用 | 过滤 (Filtering)、优先级 (Prioritization) |
Iris 基于 Fortnite 大逃杀(每服务器最多 100 名玩家)的经验,目标是更大的世界、更多玩家、更低的服务器成本。它与现有复制系统并存,现有复制属性与 RPC 定义只需小改即可兼容。核心设计是保存全部复制状态的量化 (Quantized) 副本,把复制数据与游戏线程数据分离以支持并发,并在多个对象和连接之间共享工作;它期望游戏代码在状态改变时主动通知复制系统。启用需在 .uproject 开 Iris 插件、Build.cs 调 SetupIrisSupport(Target)、Target.cs 设 bUseIris = true、ini 设 net.Iris.UseIrisReplication=1 等(构建文件见 模块、插件与构建系统)。官方提醒:实验性功能,发售时需谨慎。(Iris Replication System)
实践建议与常见坑
官方网络提示汇总(Networking Overview):
- RPC 和复制的蓝图函数越少越好;能用 RepNotify 就别用 RPC。
- 多播会给每个连接产生额外流量,慎用。
- 把可靠 RPC 绑到玩家输入要小心:狂按按键可能撑爆可靠 RPC 队列,需要限频。
- 高频调用(如在 Tick 里)的 RPC 应设为不可靠(Tick 见 委托与 Tick 机制)。
- 同一函数既在玩法逻辑中调用、又作为 RepNotify 调用,可让服务器与客户端并行执行同样逻辑。
- 检查网络角色与
IsLocallyControlled过滤执行。 - 网络休眠 (Dormancy) 是最显著的优化之一。
GAS 在此之上提供了属性复制与客户端预测的现成方案,见 Gameplay 能力系统;World Partition 中运行时数据层只能由服务器激活,见 世界分区。
出处
- Networking Overview UE 5.8 文档
- Replicate Actor Properties UE 5.8 文档
- Remote Procedure Calls UE 5.8 文档
- Actor Relevancy UE 5.8 文档
- Actor Priority UE 5.8 文档
- Actor Role/Remote Role & Owner/Owning Connection UE 5.8 文档
- Iris Replication System UE 5.8 文档