
第 19 章 · 网络同步宏驱动的状态复制多人游戏中服务器是权威角色血量、位置、背包等以服务器为准。客户端需要把这些状态同步过来并在适当时机请求服务器执行操作开火、使用技能。传统做法是手写协议、手写序列化、手写分发——工作量大且易错。Unreal 把这件事压缩成加说明符 实现一个注册函数反射知道要同步哪些属性序列化知道如何打包/解包说明符声明同步策略。本章是反射与序列化在网络维度的汇流。19.1 属性复制Replication要让一个属性在服务器和客户端之间同步UPROPERTY(Replicated)floatHealth;// 在类实现文件中voidAMyCharacter::GetLifetimeReplicatedProps(TArrayFLifetimePropertyOutLifetimeProps)const{Super::GetLifetimeReplicatedProps(OutLifetimeProps);DOREPLIFETIME(AMyCharacter,Health);}Replicated告诉网络层这个属性需要复制。GetLifetimeReplicatedProps里用DOREPLIFETIME宏把属性和复制策略如条件只给 Owner、只给相关等注册进去。引擎会在服务器上追踪该属性是否变化dirty在发送 tick 时只对变化的属性做序列化并发送客户端收到后反序列化并写回对应对象的属性。你不需要手写比较旧值新值“打包 float”“发到哪个 channel”——反射提供属性元数据序列化提供读写网络层负责调度和条件。复制条件DOREPLIFETIME 可搭配DOREPLIFETIME_CONDITION指定发给谁例如只发给该 Actor 的 OwnerCOND_OwnerOnly、只发给持有该 Actor 的 relevancy 的客户端COND_None以外的条件等从而减少带宽。反射提供属性列表条件由你在注册时声明网络层按条件决定是否把该属性包含进某客户端的更新包。19.2 ReplicatedUsing同步后的回调UPROPERTY(ReplicatedUsingOnRep_Health)floatHealth;UFUNCTION()voidOnRep_Health();ReplicatedUsing表示当 Health 从服务器同步到客户端并更新后调用OnRep_Health()。这样可以在客户端专门做血量变化的反馈更新 UI、播放音效、插值等。服务器不需要也不应该依赖 OnRepOnRep 只在接收端调用。19.3 RPC远程过程调用除了状态同步还需要在对方机器上执行一个函数UFUNCTION(Server)仅在服务器执行。客户端调用调用内容被序列化发到服务器服务器执行该函数并可作为权威修改状态。UFUNCTION(Client)仅在目标客户端执行。服务器调用可带目标 PlayerController 等用于通知某客户端如你被击中。UFUNCTION(NetMulticast)服务器调用在所有客户端及服务器上执行用于全服广播如爆炸效果。RPC 可以有参数和返回值返回值仅对 Server RPC 有意义且需注意可靠性。Reliable保证送达和顺序Unreliable可丢包适合高频、可插值的更新如位置。底层同样是反射UFunction 的签名被序列化/反序列化ProcessEvent 在目标机器上执行对应 UFunction实现按名调用。RPC 类型调用方执行方典型用途Server客户端服务器请求开火、使用技能、权威操作Client服务器指定客户端通知你被击中、播放本地特效NetMulticast服务器所有客户端 服务器爆炸、全服广播效果Reliable / Unreliable——Reliable 保证顺序与送达Unreliable 可丢包适合位置等高频数据19.4 三位一体回顾反射提供有哪些属性/函数、类型与偏移供网络层决定复制谁、调用谁。序列化FArchive 与属性类型序列化负责把属性或 RPC 参数变成字节流并在对端还原。说明符Replicated、ReplicatedUsing、Server、Client、NetMulticast、Reliable 等声明式地配置行为。这就是第 2 章全景图中反射 → 网络同步那条边的具体实现没有反射就没有自动属性复制和 RPC没有序列化就没有网络包体没有说明符就没有声明式的配置。实验最小复制与 RPC复制一个属性。在第三人称模板或空白项目中给角色类加UPROPERTY(Replicated) float TestReplicatedFloat;在 cpp 里实现GetLifetimeReplicatedProps并DOREPLIFETIME(AMyCharacter, TestReplicatedFloat);。在服务器上于 Tick 或按键时修改TestReplicatedFloat在客户端用 OnRep 或每帧打印该值确认客户端能看到服务器修改后的值。OnRep 只在客户端。在 OnRep 函数里打日志分别以 Listen Server 和独立客户端运行确认 OnRep 仅在客户端或非权威端被调用服务器端不会收到该回调。Server RPC。声明UFUNCTION(Server, Reliable) void ServerDoSomething(int32 Value);在客户端按键时调用在 ServerDoSomething_Implementation 里打日志并修改一个 Replicated 属性确认只有服务器执行 _Implementation客户端通过属性复制拿到结果。一句话总结Unreal 的网络同步由反射提供复制/调用的元数据、序列化打包解包和说明符Replicated、Server、Client 等共同完成把传统上手写协议和分发的逻辑收束为标注 注册实现属性复制和 RPC。