中EN
概念页

网络复制与 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说明
单机 StandaloneNM_Standalone也被视为服务器,但不接受远程连接;同时跑服务器与客户端逻辑
专用服务器 Dedicated ServerNM_DedicatedServer无本地玩家,丢弃图形/声音/输入;公平、高效,适合 MMO、竞技 MOBA、快节奏射击
监听服务器 Listen ServerNM_ListenServer主机同时是玩家;易搭建,但主机有优势且负载更高,适合休闲合作/对抗
客户端 ClientNM_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连接的远端永不在本地执行;未暴露给蓝图

(Remote Procedure Calls)

下图展示一次“客户端开火”在网络上的典型路径:客户端向服务器发 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_AuthorityROLE_AutonomousProxy服务器某客户端控制的 Pawn
ROLE_AutonomousProxyROLE_Authority客户端本客户端控制的 Pawn
ROLE_SimulatedProxyROLE_Authority客户端其他玩家的 Pawn 或无人控制的复制 Actor
ROLE_AuthorityROLE_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)

(Networking Overview)

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 中运行时数据层只能由服务器激活,见 世界分区。

  1. Networking Overview UE 5.8 文档
  2. Replicate Actor Properties UE 5.8 文档
  3. Remote Procedure Calls UE 5.8 文档
  4. Actor Relevancy UE 5.8 文档
  5. Actor Priority UE 5.8 文档
  6. Actor Role/Remote Role & Owner/Owning Connection UE 5.8 文档
  7. Iris Replication System UE 5.8 文档

相关页面

游戏开发快照压缩与增量编码Snapshot Compression & Delta Encoding提高快照率以降低插值延迟,必须把每快照比特打下来:有界量化、四元数「最小三分量」、静止省略,以及相对对端已确认基线的增量编码。Source 的 delta snapshot 与 ack 跟踪是同一家族的工程实现。游戏开发UDP 与游戏协议设计UDP & Game Protocol Design动作游戏的时间关键数据(输入、位姿、物理)只关心最新状态。TCP 的可靠有序流会在丢包时把头阻塞住;正确做法是游戏协议只走 UDP,自己做虚拟连接、按需可靠性与拥塞退避,并按数据类型选择「冗余重发」还是「直接丢弃旧包」。游戏开发延迟补偿Lag Compensation服务器在执行玩家开火等用户命令前,把其他玩家(及必要状态)回拨到「该命令在客户端生成时」所对应的世界时刻——扣除包延迟与客户端视图插值——再做命中判定,然后恢复。这样玩家可以对着自己屏幕上看到的目标直接开火,而不必凭感觉提前量;代价是可能出现「拐角后仍被击中」等时间悖论。游戏开发快照插值Snapshot Interpolation发送端按固定频率拍下世界(或相关子集)的快照,接收端不跑权威模拟,而是把渲染时刻拨回一小段,在缓冲里的两份快照之间插值,用额外延迟换平滑,并扛住抖动与偶发丢包。Source 的实体插值与 clinterp 是同一思想的产品化。游戏开发客户端预测与纠正重放Client-Side Prediction & Reconciliation本地客户端立刻用与服务器相同的运动(及可选武器)代码根据输入推进自己的角色,消除操作往返延迟;服务器仍是权威。权威纠正到达时已是「过去」,客户端丢弃过期缓冲、回绕到纠正状态再重放未确认输入,得到与服务器一致的「现在」。游戏开发多人网络游戏模型Multiplayer Networking Models多人游戏并不是共享同一份物理现实,而是每位玩家各自看到的近似。历史上主要两条路:对等锁步 (Peer-to-Peer Lockstep)(RTS 仍常用)与权威客户端/服务器 (Authoritative Client/Server)(动作/FPS 主流);后者再叠加客户端预测、插值与延迟补偿,把延迟藏进体验里。游戏开发 · UE5Gameplay 框架Gameplay FrameworkGameplay 框架 (Gameplay Framework) 是 UE 提供的一组相互配合的类,用来搭建游戏的基本结构:Actor 与组件 (Component) 构成场景中的一切;GameMode 在服务器上定规则并生成玩家;玩家由“控制器 (Controller) + 棋子 (Pawn)”组成;GameState 与 PlayerState 负责把全局与每个玩家的状态复制给所有客户端;GameInstance 跨关卡存活。游戏开发 · UE5UObject 与反射系统UObject & Reflection System虚幻引擎 (Unreal Engine) 的对象基类是 UObject。在 C++ 类、属性、函数上加 UCLASS/UPROPERTY/UFUNCTION 等宏,再由构建前的预处理工具虚幻头文件工具 (Unreal Header Tool, UHT) 扫描头文件生成代码,引擎就能在运行时“看见”这些类型——这就是反射系统 (Reflection System)。垃圾回收、序列化、编辑器面板、蓝图、网络复制都建立在它之上。游戏开发 · UE5Gameplay 能力系统Gameplay Ability SystemGameplay 能力系统 (Gameplay Ability System, GAS) 是 UE 用来构建「Actor 可拥有并反复触发的能力」的框架:能力系统组件 (Ability System Component, ASC) 是持有者,Gameplay 能力 (Gameplay Ability) 编排执行过程,属性集 (Attribute Set) 存数值,Gameplay 效果 (Gameplay Effect, GE) 改数值和标签,Gameplay 标签 (Gameplay Tags) 做状态与互斥,Gameplay Cue 负责表现。它内建复制与客户端预测,代价是概念多、上手重,游戏开发 · UE5委托与 Tick 机制Delegates & TickUE 有两种驱动游戏逻辑的方式:事件驱动——委托 (Delegate) 在某事发生时回调绑定的函数;轮询驱动——Tick 每帧(或按最小间隔)调用 Actor/组件的更新函数,并按 Tick 组 (Tick Group) 与物理模拟排序。官方建议能用定时器、委托就不用 Tick,必须 Tick 时用 Tick 组和 Tick 依赖保证顺序,避免“差一帧”问题。游戏开发 · UE5MassEntity 数据导向框架MassEntity FrameworkMassEntity 是 UE5 面向玩法的数据导向 (Data-Oriented) 计算框架,属于实体-组件-系统 (Entity Component System, ECS) 一类设计:实体 (Entity) 只是一个 ID 加上一组片段 (Fragment) 数据,相同组成的实体归入同一原型 (Archetype) 并按内存块 (Chunk) 连续存放,无状态的处理器 (Processor) 通过实体查询 (EntityQuery) 批量处理片段。它适合成千上万个同质对象(人群、交通),MassGameplay 插件在其上提供表现、生成、LOD、复制、StateTree 等功能。游戏开发 · UE5世界分区World Partition世界分区 (World Partition) 是 UE5 的自动数据管理与基于距离的关卡流送 (Level Streaming) 系统:整个世界存为一个持久关卡,按可配置的运行时网格划分为单元格 (Cell),由流送源 (Streaming Source,默认是玩家控制器) 按距离加载/卸载。它配合一 Actor 一文件 (One File Per Actor, OFPA) 支持多人协作编辑,用数据层 (Data Layers) 按玩法状态切换内容,用分层细节层次 (Hierarchical Level of Detail, HLOD) 在远处以代理网格显示未加载的单元格。游戏开发 · UE5动画蓝图与动画系统Animation Blueprint & Animation SystemUE5 角色动画以动画蓝图 (Animation Blueprint) 为核心:它每帧为骨骼网格体 (Skeletal Mesh) 计算最终姿势。动画蓝图内部用状态机 (State Machine) 组织“何时播什么”,用混合空间 (Blend Space) 按速度、方向等参数连续混合,用蒙太奇 (Animation Montage) 在插槽 (Slot) 中插播攻击、交互等一次性动作,用 Control Rig 做程序化骨骼控制(如贴地)。算出的骨骼姿势最终交给蒙皮 (Skinning) 驱动顶点。游戏开发 · UE5Chaos 物理与碰撞Chaos Physics & CollisionChaos 是 UE5 的物理与破碎系统。日常最常打交道的是碰撞模型:每个物理体有对象类型 (Object Type) 和对其他类型的 Block/Overlap/Ignore 响应,结果由双方共同决定;Hit 与 Overlap 事件都要显式开启。骨骼网格通过物理资产 (Physics Asset) 获得刚体与约束(布娃娃、物理动画);Chaos 破碎基于几何集合 (Geometry Collection) 的分级断裂、簇阈值、连接图与缓存回放,并能把事件交给 Niagara。物理体用盒/球/胶囊/凸包代理,原理对应游戏数学中的包围体与相交测试。游戏开发 · UE5专用服务器Dedicated ServerUE 多人游戏采用客户端-服务器模型。监听服务器 (listen server) 由某个玩家的客户端兼任服务器;专用服务器 (dedicated server) 无头运行,不渲染画面,也没有本地玩家。专用服务器体积更小、房主没有不公平优势、能专注于玩法逻辑,适合大规模或竞技游戏。构建专用服务器需要源码版引擎和支持客户端-服务器的 C++ 项目,并要有 <ProjectServer.Target.cs。游戏开发 · UE5角色移动组件与 MoverCharacter Movement Component & Mover角色移动组件 (CMC) 用「客户端预测 + 服务器校验 + 纠正后重放」实现联网移动:自主代理先在本地移动并把操作存起来,用 ServerMove RPC 发给服务器重演,位置不符时服务器用 ClientAdjustPosition 纠正,客户端再按保存的操作重放;模拟代理只应用复制下来的移动并做平滑。实验性插件 Mover 计划接替 CMC,改用共享时间线、回滚与重模拟的模型,并且更模块化。游戏开发 · UE5复制图Replication Graph复制图 (Replication Graph) 插件解决的是服务器 CPU 瓶颈:标准做法是让每个复制 Actor 对每个连接各自判断是否需要发送,玩家和 Actor 一多(Fortnite 大逃杀开局有 100 名玩家、约 5 万个复制 Actor)就撑不住。复制图由持久存在的节点组成,按空间网格、休眠、常驻相关等规则预先分组,并缓存可跨帧、跨连接共享的复制列表。游戏开发 · UE5Gameplay 调试器与可视化日志Gameplay Debugger & Visual LoggerGameplay 调试器 (GDT) 用于在运行时实时查看玩法数据(Pawn、AIController、行为树与黑板、EQS、感知、导航网格),联网时客户端也能看,并且只复制已启用类别的数据。可视化日志 (Visual Logger) 则把 Actor 的状态和图形化信息录下来,之后在编辑器里按时间轴来回拖动查看,适合排查难以复现的 bug。游戏开发 · UE5在线子系统与 EOSOnline Subsystem & EOSOnline Subsystem (OSS) 是 UE 访问 Steam、Xbox Live、Epic 等在线服务的统一抽象:按功能分成身份 (Identity)、会话 (Session)、好友、成就等接口,所有远程操作都是异步的,用委托回调。UE 5.1 起新增了 Online Services 插件(5.8 中仍为 Beta),返回 TOnlineAsyncOpHandle 句柄。Epic Online Services 通过 OSS EOS 插件接入;在 Steam 等其他平台发行时,可以再叠加 EOS Plus 插件。游戏策划多人游戏与社区Multiplayer & Communities人是社会动物,历史上大多数游戏都是与他人或对抗他人玩的;电子游戏以单人为主只是由新奇感和技术限制造成的暂时反常。人们与他人一起玩有五个原因:竞争、合作、相聚、探索朋友、探索自我;还要考虑观众与防作弊。玩家进一步会形成社区,社区满足社交需要、延长"传染期"、增加游戏时长。Schell 给出建设社区的十条建议、以及应对恶意玩家 (griefing) 的系统设计;两章共六面透镜 95–99(含第 3 版新增的 95 观赏、95½ 可作弊性)(第 3 版第 24–25 章)。游戏策划游戏操控Game Controls"三个 C"的最后一个,也是唯一对所有游戏都适用的一个(抽象解谜、载具模拟没有角色,老式固定画面没有镜头)。Rogers 的核心原则:玩游戏的是人——手指短、运动协调一般,所以操控要讲人体工学;按下按键,动作就要发生;任何按键都不能"什么也不做";镜头相对还是角色相对,选一种坚持到底;触屏、震动与体感要语言一致、贴近现实动作(Level Up! 第 3 版 Level 7 The Three Cs, Part 3: Controls,p.171–187)。游戏开发 · UE5增强输入Enhanced Input增强输入 (Enhanced Input) 是 UE5 默认启用的输入插件,把输入拆成四层:输入动作 (Input Action) 表示“玩家想做什么”,输入映射上下文 (Input Mapping Context) 规定“哪些按键在什么情境下触发它”,输入修饰器 (Input Modifier) 预处理原始值,输入触发器 (Input Trigger) 判定是否触发。上下文可在运行时按优先级增删,从而用数据资产而非代码处理情境切换、按键冲突与改键。游戏开发 · UE5模块、插件与构建系统Modules, Plugins & Build SystemUE 的代码由模块 (Module) 组成:每个模块是一个独立编译单元,用 [模块名].Build.cs 声明依赖。插件 (Plugin) 是可按项目启用/禁用的代码与内容集合,用 .uplugin 描述,可包含多个模块。虚幻构建工具 (UnrealBuildTool, UBT) 根据 .Target.cs 和 .Build.cs(而不是 IDE 的 .sln)编译,默认把模块编成 DLL 由一个可执行文件加载,也可整体链接成单体 (Monolithic) 可执行文件。图形学细节层次Level of Detail细节层次 (LOD) 在物体对图像贡献变小时改用更简单的表示。LOD 系统由三部分组成:生成(简化或手工制作多个版本)、选择(按距离、投影面积等收益函数挑选)、切换(尽量减少跳变 popping)。LOD 主要减少顶点处理,也通过减少 quad 过度着色降低像素开销;进一步还可在预算约束下全局选择 LOD,实现时间关键(恒定帧率)渲染。

被这些页面引用1 篇

输入关键词开始搜索

滚轮或双指缩放 · 拖动平移 · 双击放大 / 还原