ue-networking-replication
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseUE Networking & Replication
UE 网络与复制系统
You are an expert in Unreal Engine's networking and replication systems.
你是Unreal Engine网络与复制系统方面的专家。
Context Check
上下文检查
Read for this project's multiplayer configuration.
Look for: server topology (dedicated, listen, P2P), player count, replicated classes,
and any custom net drivers.
.agents/ue-project-context.mdIf the context file is absent, ask:
- Server topology? (dedicated, listen, P2P)
- Maximum player count per session?
- Which actors or components need to replicate data?
- Are you using Gameplay Ability System (GAS)?
阅读了解本项目的多人游戏配置。需关注:服务器拓扑(dedicated、listen、P2P)、玩家数量、可复制类以及任何自定义网络驱动。
.agents/ue-project-context.md如果上下文文件不存在,请询问:
- 服务器拓扑?(dedicated、listen、P2P)
- 每个会话的最大玩家数?
- 哪些Actor或组件需要复制数据?
- 是否在使用Gameplay Ability System(GAS)?
Net Roles and Authority
网络角色与权限
UE uses a server-authoritative model: the server is the source of truth for game state.
Clients predict locally and reconcile with server corrections.
Every actor on every machine has a local role and a remote role ().
ENetRoleROLE_Authority — owns and can modify this actor (server for replicated actors)
ROLE_AutonomousProxy — client copy of the locally controlled pawn
ROLE_SimulatedProxy — client copy of another player's actor; engine interpolates state
ROLE_None — not replicatedFrom :
Actor.hcpp
ENetRole GetLocalRole() const { return Role; } // role on current machine
ENetRole GetRemoteRole() const; // role the other end sees
bool HasAuthority() const { return (GetLocalRole() == ROLE_Authority); }Net modes: , , , .
NM_StandaloneNM_DedicatedServerNM_ListenServerNM_ClientRole matrix for a replicated Pawn:
| Machine | GetLocalRole() | GetRemoteRole() |
|---|---|---|
| Server | ROLE_Authority | ROLE_AutonomousProxy or SimulatedProxy |
| Owning Client | ROLE_AutonomousProxy | ROLE_Authority |
| Other Clients | ROLE_SimulatedProxy | ROLE_Authority |
Listen-server caveat: the host is both and locally controlled.
Use to distinguish logic that should skip the host player.
ROLE_AuthorityIsLocallyControlled()UE采用服务器权威模型:服务器是游戏状态的唯一可信源。客户端进行本地预测,并根据服务器的修正进行协调。
每台机器上的每个Actor都拥有一个本地角色和一个远程角色()。
ENetRoleROLE_Authority — owns and can modify this actor (server for replicated actors)
ROLE_AutonomousProxy — client copy of the locally controlled pawn
ROLE_SimulatedProxy — client copy of another player's actor; engine interpolates state
ROLE_None — not replicated来自:
Actor.hcpp
ENetRole GetLocalRole() const { return Role; } // role on current machine
ENetRole GetRemoteRole() const; // role the other end sees
bool HasAuthority() const { return (GetLocalRole() == ROLE_Authority); }网络模式:、、、。
NM_StandaloneNM_DedicatedServerNM_ListenServerNM_Client可复制Pawn的角色矩阵:
| 机器类型 | GetLocalRole() | GetRemoteRole() |
|---|---|---|
| 服务器 | ROLE_Authority | ROLE_AutonomousProxy 或 SimulatedProxy |
| 所属客户端 | ROLE_AutonomousProxy | ROLE_Authority |
| 其他客户端 | ROLE_SimulatedProxy | ROLE_Authority |
监听服务器注意事项: 主机同时拥有权限且受本地控制。使用来区分需要跳过主机玩家的逻辑。
ROLE_AuthorityIsLocallyControlled()UNetDriver
UNetDriver
UNetDriverUNetConnectionUWorld::GetNetDriver()cpp
UNetDriver* Driver = GetWorld()->GetNetDriver();
// Driver->ClientConnections — all connected clients (server-side)
// Driver->ServerConnection — connection to server (client-side)For most gameplay code you never interact with directly; it is relevant when
writing custom net drivers, profiling connection state, or debugging packet loss.
UNetDriverUNetDriverUNetConnectionUWorld::GetNetDriver()cpp
UNetDriver* Driver = GetWorld()->GetNetDriver();
// Driver->ClientConnections — all connected clients (server-side)
// Driver->ServerConnection — connection to server (client-side)对于大多数游戏玩法代码,你无需直接与交互;仅在编写自定义网络驱动、分析连接状态或调试丢包问题时才会用到它。
UNetDriverProperty Replication
属性复制
Actor Setup
Actor 设置
cpp
AMyActor::AMyActor()
{
bReplicates = true; // AActor::SetReplicates() also available at runtime
SetReplicateMovement(true); // replicates FRepMovement (location/rotation/velocity)
SetNetUpdateFrequency(10.f); // checks per second
SetMinNetUpdateFrequency(2.f); // floor when nothing changes
NetPriority = 1.0f; // higher = preferred when bandwidth is saturated
}From : , , ,
, and are all .
Actor.hSetReplicatesSetReplicateMovementSetNetUpdateFrequencySetMinNetUpdateFrequencySetNetCullDistanceSquaredENGINE_APIFRepMovement: when , the engine serializes position,
velocity, and rotation into an struct (declared in ) and
sends it to simulated proxies. bypasses this with its
own prediction-based replication; it writes compressed moves via
and reconciles them server-side, so is the correct
default for characters using CMC.
bReplicateMovement = trueFRepMovementActor.hUCharacterMovementComponentFSavedMove_CharacterSetReplicateMovement(false)cpp
AMyActor::AMyActor()
{
bReplicates = true; // AActor::SetReplicates() also available at runtime
SetReplicateMovement(true); // replicates FRepMovement (location/rotation/velocity)
SetNetUpdateFrequency(10.f); // checks per second
SetMinNetUpdateFrequency(2.f); // floor when nothing changes
NetPriority = 1.0f; // higher = preferred when bandwidth is saturated
}来自:、、、和均为。
Actor.hSetReplicatesSetReplicateMovementSetNetUpdateFrequencySetMinNetUpdateFrequencySetNetCullDistanceSquaredENGINE_APIFRepMovement: 当时,引擎会将位置、速度和旋转序列化为结构体(在中声明)并发送给模拟代理。通过其基于预测的复制机制绕过了这一过程;它通过写入压缩的移动数据,并在服务器端进行协调,因此对于使用CMC的角色,正确的默认设置是。
bReplicateMovement = trueFRepMovementActor.hUCharacterMovementComponentFSavedMove_CharacterSetReplicateMovement(false)Declaring Properties
声明属性
cpp
UPROPERTY(Replicated)
int32 Health;
UPROPERTY(ReplicatedUsing = OnRep_State)
EMyState State;
UFUNCTION()
void OnRep_State(EMyState PreviousState); // old value passed as optional parametercpp
UPROPERTY(Replicated)
int32 Health;
UPROPERTY(ReplicatedUsing = OnRep_State)
EMyState State;
UFUNCTION()
void OnRep_State(EMyState PreviousState); // old value passed as optional parameterGetLifetimeReplicatedProps
GetLifetimeReplicatedProps
cpp
// MyActor.cpp
#include "Net/UnrealNetwork.h"
void AMyActor::GetLifetimeReplicatedProps(
TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps); // NEVER omit this
DOREPLIFETIME(AMyActor, Health);
DOREPLIFETIME_CONDITION(AMyActor, State, COND_OwnerOnly);
DOREPLIFETIME_CONDITION(AMyActor, SimData, COND_SimulatedOnly);
DOREPLIFETIME_CONDITION(AMyActor, InitData, COND_InitialOnly);
DOREPLIFETIME_CONDITION(AMyActor, PublicData, COND_SkipOwner);
}Conditions: (all), , ,
, , , .
COND_NoneCOND_OwnerOnlyCOND_SkipOwnerCOND_SimulatedOnlyCOND_AutonomousOnlyCOND_InitialOnlyCOND_CustomUse for private player data (inventory, currency).
Use for immutable spawn data (team, character class).
COND_OwnerOnlyCOND_InitialOnlyInitial replication burst: When a client first joins or an actor first becomes relevant, ALL replicated properties send at once regardless of conditions ( fires exactly once here). This burst can saturate the actor channel — keep initial state compact and use for spawn-time-only data to reduce ongoing bandwidth.
COND_InitialOnlyCOND_InitialOnlycpp
// MyActor.cpp
#include "Net/UnrealNetwork.h"
void AMyActor::GetLifetimeReplicatedProps(
TArray<FLifetimeProperty>& OutLifetimeProps) const
{
Super::GetLifetimeReplicatedProps(OutLifetimeProps); // NEVER omit this
DOREPLIFETIME(AMyActor, Health);
DOREPLIFETIME_CONDITION(AMyActor, State, COND_OwnerOnly);
DOREPLIFETIME_CONDITION(AMyActor, SimData, COND_SimulatedOnly);
DOREPLIFETIME_CONDITION(AMyActor, InitData, COND_InitialOnly);
DOREPLIFETIME_CONDITION(AMyActor, PublicData, COND_SkipOwner);
}条件: (所有客户端)、、、、、、。
COND_NoneCOND_OwnerOnlyCOND_SkipOwnerCOND_SimulatedOnlyCOND_AutonomousOnlyCOND_InitialOnlyCOND_CustomCOND_OwnerOnlyCOND_InitialOnly初始复制爆发: 当客户端首次加入或Actor首次变得相关时,所有可复制属性会一次性发送,不受条件限制(在此处仅触发一次)。这种爆发可能会占用Actor通道的带宽——请保持初始状态简洁,并使用处理仅生成时需要的数据,以减少持续带宽消耗。
COND_InitialOnlyCOND_InitialOnlyFRepLayout (Internal)
FRepLayout(内部)
FRepLayoutDOREPLIFETIME_CONDITIONFRepLayoutDOREPLIFETIME_WITH_PARAMS_FASTbIsPushBasedFRepLayoutDOREPLIFETIME_CONDITIONFRepLayoutDOREPLIFETIME_WITH_PARAMS_FASTbIsPushBasedLarge Arrays: FFastArraySerializer
大型数组:FFastArraySerializer
Plain sends the full array on any change. Use for
delta-only replication. See Pattern 3 for
a complete inventory implementation.
TArrayFFastArraySerializerreferences/replication-patterns.md普通在任何变化时都会发送整个数组。对于仅增量复制的场景,请使用。完整的背包实现请参考中的模式3。
TArrayFFastArraySerializerreferences/replication-patterns.mdCustom Struct Serialization
自定义结构体序列化
Implement on a and add with
to control binary layout manually. Use
(0.1 cm precision) instead of raw to halve
position bandwidth.
NetSerializeUSTRUCTTStructOpsTypeTraitsWithNetSerializer = trueFVector_NetQuantize10FVector在上实现,并添加且设置,以手动控制二进制布局。使用(精度0.1厘米)替代原始,可将位置数据的带宽减少一半。
USTRUCTNetSerializeTStructOpsTypeTraitsWithNetSerializer = trueFVector_NetQuantize10FVectorRemote Procedure Calls (RPCs)
远程过程调用(RPC)
See for the full decision flowchart.
references/rpc-decision-guide.mdcpp
// Client calls → server executes. WithValidation is required for state changes.
UFUNCTION(Server, Reliable, WithValidation)
void ServerFireWeapon(FVector_NetQuantize Origin, FVector_NetQuantizeNormal Dir);
// Server calls → owning client executes. No WithValidation needed.
UFUNCTION(Client, Reliable)
void ClientShowKillConfirm();
// Server calls → server + all clients execute.
UFUNCTION(NetMulticast, Unreliable)
void MulticastPlayHitEffect(FVector ImpactPoint);Implementations always end in . Server RPCs with validation also
need (return to kick the client).
_Implementation_ValidatefalseReliable — guaranteed delivery; use for state-changing actions (purchase, spawn,
possession). Unreliable — fire-and-forget; use for high-frequency cosmetics.
Real examples from :
PlayerController.hcpp
UFUNCTION(unreliable, server, WithValidation) void ServerSetSpectatorLocation(...);
UFUNCTION(reliable, server, WithValidation) void ServerAcknowledgePossession(APawn* P);
UFUNCTION(Reliable, Client) void ClientReceiveLocalizedMessage(...);
UFUNCTION(Client, Unreliable) void ClientAckTimeDilation(float, int32);RPC ownership: Server RPCs must be called on an actor whose ownership chain
leads to the calling client's . Client RPCs must be called on
an actor owned by a player with a . Calls on unowned actors are
silently dropped.
APlayerControllerNetConnectionRPC Parameter Rules: Only net-addressable types are valid — basic types (,
, , ), replicated pointers (arrive as
if not replicated), and structs. Non-replicated
pointers arrive as ; pass an ID and look the object up on the remote side.
Large payloads (>1 KB) should use replicated properties instead of RPC parameters.
and parameters are supported but watch for bandwidth impact.
int32floatFStringFVectorUObject*nullptrUSTRUCT(BlueprintType)UObject*nullptrTArrayTMap完整的决策流程图请参考。
references/rpc-decision-guide.mdcpp
// Client calls → server executes. WithValidation is required for state changes.
UFUNCTION(Server, Reliable, WithValidation)
void ServerFireWeapon(FVector_NetQuantize Origin, FVector_NetQuantizeNormal Dir);
// Server calls → owning client executes. No WithValidation needed.
UFUNCTION(Client, Reliable)
void ClientShowKillConfirm();
// Server calls → server + all clients execute.
UFUNCTION(NetMulticast, Unreliable)
void MulticastPlayHitEffect(FVector ImpactPoint);实现函数的名称必须以结尾。带有验证的Server RPC还需要函数(返回会踢掉客户端)。
_Implementation_ValidatefalseReliable(可靠) — 保证送达;用于改变状态的操作(如购买、生成、占有)。Unreliable(不可靠) — 发送后无需确认;用于高频次的外观效果。
来自的真实示例:
PlayerController.hcpp
UFUNCTION(unreliable, server, WithValidation) void ServerSetSpectatorLocation(...);
UFUNCTION(reliable, server, WithValidation) void ServerAcknowledgePossession(APawn* P);
UFUNCTION(Reliable, Client) void ClientReceiveLocalizedMessage(...);
UFUNCTION(Client, Unreliable) void ClientAckTimeDilation(float, int32);RPC所有权: Server RPC必须在其所有权链指向调用客户端的的Actor上调用。Client RPC必须在由拥有的玩家所拥有的Actor上调用。在无所有权的Actor上调用会被静默丢弃。
APlayerControllerNetConnectionRPC参数规则: 仅支持可网络寻址的类型——基础类型(、、、)、可复制的指针(如果未复制则会变为)以及结构体。不可复制的指针会变为;请传递ID并在远程端查找对象。大型负载(>1 KB)应使用可复制属性而非RPC参数。支持和参数,但需注意带宽影响。
int32floatFStringFVectorUObject*nullptrUSTRUCT(BlueprintType)UObject*nullptrTArrayTMapOwnership and Relevancy
所有权与相关性
cpp
// Server sets owner to control connection routing for RPCs and COND_OwnerOnly
Weapon->SetOwner(PlayerController);
// Relevancy flags (from Actor.h)
bAlwaysRelevant = true; // replicate to every connection
bOnlyRelevantToOwner = true; // replicate only to the owning connection
// Override for custom logic (e.g., team-based relevancy)
virtual bool IsNetRelevantFor(const AActor* RealViewer, const AActor* ViewTarget,
const FVector& SrcLocation) const override;Default relevancy culls actors beyond from the client
viewpoint. determines which actors win when bandwidth is saturated.
NetCullDistanceSquaredNetPriorityDormancy: actors that rarely change can pause replication entirely.
cpp
SetNetDormancy(DORM_DormantAll); // stop replication
FlushNetDormancy(); // send one update then return to dormantRe-relevancy: When an actor moves outside it stops replicating. When it returns to range, the engine treats it as a fresh relevancy event — sending another initial burst and firing all callbacks with current server state. Design functions to be idempotent (tolerate being called multiple times with the same value). Dormant actors () behave similarly when woken — they flush all dirty properties at once.
NetCullDistanceSquaredOnRep_OnRep_DORM_DormantAllcpp
// Server sets owner to control connection routing for RPCs and COND_OwnerOnly
Weapon->SetOwner(PlayerController);
// Relevancy flags (from Actor.h)
bAlwaysRelevant = true; // replicate to every connection
bOnlyRelevantToOwner = true; // replicate only to the owning connection
// Override for custom logic (e.g., team-based relevancy)
virtual bool IsNetRelevantFor(const AActor* RealViewer, const AActor* ViewTarget,
const FVector& SrcLocation) const override;默认相关性会剔除客户端视角超出范围的Actor。当带宽饱和时,决定哪些Actor会优先被复制。
NetCullDistanceSquaredNetPriority休眠: 很少变化的Actor可以完全暂停复制。
cpp
SetNetDormancy(DORM_DormantAll); // stop replication
FlushNetDormancy(); // send one update then return to dormant重新相关性: 当Actor移动到范围外时,复制会停止。当它回到范围内时,引擎会将其视为新的相关性事件——再次发送初始爆发数据,并使用当前服务器状态触发所有回调。请将函数设计为幂等的(能够容忍多次使用相同值调用)。休眠的Actor()被唤醒时的行为类似——它们会一次性发送所有脏属性。
NetCullDistanceSquaredOnRep_OnRep_DORM_DormantAllSubobject Replication
子对象复制
Modern API (UE 5.1+)
现代API(UE 5.1+)
From :
Actor.hcpp
ENGINE_API void AddReplicatedSubObject(UObject* SubObject,
ELifetimeCondition NetCondition = COND_None);
ENGINE_API void RemoveReplicatedSubObject(UObject* SubObject);
ENGINE_API void AddActorComponentReplicatedSubObject(UActorComponent* OwnerComponent,
UObject* SubObject,
ELifetimeCondition NetCondition = COND_None);Enable with (now the default).
Call on the server during ; call
in .
bReplicateUsingRegisteredSubObjectList = trueAddReplicatedSubObjectBeginPlayRemoveReplicatedSubObjectEndPlay来自:
Actor.hcpp
ENGINE_API void AddReplicatedSubObject(UObject* SubObject,
ELifetimeCondition NetCondition = COND_None);
ENGINE_API void RemoveReplicatedSubObject(UObject* SubObject);
ENGINE_API void AddActorComponentReplicatedSubObject(UActorComponent* OwnerComponent,
UObject* SubObject,
ELifetimeCondition NetCondition = COND_None);通过设置启用(现为默认设置)。在服务器的期间调用;在中调用。
bReplicateUsingRegisteredSubObjectList = trueBeginPlayAddReplicatedSubObjectEndPlayRemoveReplicatedSubObjectLegacy API
旧版API
Override when :
ReplicateSubobjectsbReplicateUsingRegisteredSubObjectList = falsecpp
bool AMyActor::ReplicateSubobjects(UActorChannel* Channel,
FOutBunch* Bunch, FReplicationFlags* RepFlags)
{
bool bWrote = Super::ReplicateSubobjects(Channel, Bunch, RepFlags);
bWrote |= Channel->ReplicateSubobject(MySubObject, *Bunch, *RepFlags);
return bWrote;
}当时,重写:
bReplicateUsingRegisteredSubObjectList = falseReplicateSubobjectscpp
bool AMyActor::ReplicateSubobjects(UActorChannel* Channel,
FOutBunch* Bunch, FReplicationFlags* RepFlags)
{
bool bWrote = Super::ReplicateSubobjects(Channel, Bunch, RepFlags);
bWrote |= Channel->ReplicateSubobject(MySubObject, *Bunch, *RepFlags);
return bWrote;
}Client-Side Prediction
客户端预测
Pattern (for non-movement systems without GAS):
cpp
// 1. Client predicts immediately
void AMyCharacter::LocalPredictAbility(int32 AbilityId)
{
if (IsLocallyControlled())
{
ApplyAbilityEffectLocal(AbilityId); // immediate visual/audio
ServerActivateAbility(AbilityId); // request server confirmation
}
}
// 2. Server validates, broadcasts, or corrects
void AMyCharacter::ServerActivateAbility_Implementation(int32 AbilityId)
{
if (CanActivateAbility(AbilityId))
{
ApplyAbilityEffectAuthority(AbilityId);
MulticastAbilityActivated(AbilityId);
}
else
{
ClientCorrectionAbilityFailed(AbilityId); // roll back client prediction
}
}When the server rejects a prediction, smooth the visual correction to avoid jarring
snaps: interpolate the actor to the corrected position over 2-3 frames rather than
teleporting. handles this automatically via
(, , or ).
UCharacterMovementComponentNetworkSmoothingModeLinearExponentialDisabledCharacterMovementComponent has full built-in prediction. Extend
and override to support custom movement modes.
FSavedMove_CharacterPhysCustomPrediction eligibility: Only and GAS ( with ) have engine-managed prediction and rollback. Raw properties have no built-in prediction — if you write them locally before the server confirms, the server's replicated value overwrites the client value with no rollback. For non-CMC/GAS state, use local-only variables for visual prediction and apply the authoritative value in .
UCharacterMovementComponentUAbilitySystemComponentFPredictionKeyUPROPERTY(Replicated)OnRep_GAS and FPredictionKey: GAS uses to link client-predicted actions
with server confirmations. The key is generated on the client (via
), embedded in the Server RPC, and matched on the
server when applying s or activating abilities. If the server determines
the prediction was invalid, every and attribute change tagged with that
key is automatically rolled back on the client. You do not construct
manually in most cases; manages the
lifecycle. Relevant when writing custom subclasses that need
scoped prediction windows (). See
for the full GAS networking details.
FPredictionKeyFPredictionKey::CreateNewPredictionKeyGameplayEffectGameplayEffectFPredictionKeyUAbilitySystemComponent::TryActivateAbilityUGameplayAbilityFScopedPredictionWindowue-gameplay-abilities模式(适用于无GAS的非移动系统):
cpp
// 1. Client predicts immediately
void AMyCharacter::LocalPredictAbility(int32 AbilityId)
{
if (IsLocallyControlled())
{
ApplyAbilityEffectLocal(AbilityId); // immediate visual/audio
ServerActivateAbility(AbilityId); // request server confirmation
}
}
// 2. Server validates, broadcasts, or corrects
void AMyCharacter::ServerActivateAbility_Implementation(int32 AbilityId)
{
if (CanActivateAbility(AbilityId))
{
ApplyAbilityEffectAuthority(AbilityId);
MulticastAbilityActivated(AbilityId);
}
else
{
ClientCorrectionAbilityFailed(AbilityId); // roll back client prediction
}
}当服务器拒绝预测时,请平滑视觉修正以避免突兀的跳转:在2-3帧内将Actor插值到修正后的位置,而非直接传送。通过(、或)自动处理此问题。
UCharacterMovementComponentNetworkSmoothingModeLinearExponentialDisabledCharacterMovementComponent 内置完整的预测功能。扩展并重写以支持自定义移动模式。
FSavedMove_CharacterPhysCustom预测资格: 只有和GAS(带有的)拥有引擎管理的预测和回滚机制。原始的属性没有内置预测——如果你在服务器确认前本地修改它们,服务器的复制值会覆盖客户端的值且不会回滚。对于非CMC/GAS状态,请使用本地变量进行视觉预测,并在中应用权威值。
UCharacterMovementComponentFPredictionKeyUAbilitySystemComponentUPROPERTY(Replicated)OnRep_GAS与FPredictionKey: GAS使用将客户端预测的操作与服务器确认关联起来。该密钥在客户端生成(通过),嵌入到Server RPC中,并在服务器应用或激活技能时进行匹配。如果服务器判定预测无效,所有带有该密钥的和属性变更会在客户端自动回滚。大多数情况下你无需手动构造;会管理其生命周期。在编写需要作用域预测窗口的自定义子类时会用到相关内容()。完整的GAS网络细节请查看。
FPredictionKeyFPredictionKey::CreateNewPredictionKeyGameplayEffectGameplayEffectFPredictionKeyUAbilitySystemComponent::TryActivateAbilityUGameplayAbilityFScopedPredictionWindowue-gameplay-abilitiesActor Replication Setup Checklist
Actor复制设置检查清单
[ ] bReplicates = true in constructor
[ ] SetNetUpdateFrequency / SetMinNetUpdateFrequency set appropriately
[ ] All UPROPERTY(Replicated) / UPROPERTY(ReplicatedUsing=...) declared
[ ] GetLifetimeReplicatedProps overridden; Super called first
[ ] DOREPLIFETIME / DOREPLIFETIME_CONDITION for each property
[ ] OnRep_ functions declared UFUNCTION() and implemented
[ ] Server RPCs have WithValidation; _Validate implemented
[ ] NetMulticast / Client RPCs guarded with HasAuthority() on call site
[ ] Subobjects registered via AddReplicatedSubObject or ReplicateSubobjects
[ ] SetOwner() called on server after spawning owned actors
[ ] DORM_DormantAll set on actors that rarely update[ ] bReplicates = true in constructor
[ ] SetNetUpdateFrequency / SetMinNetUpdateFrequency set appropriately
[ ] All UPROPERTY(Replicated) / UPROPERTY(ReplicatedUsing=...) declared
[ ] GetLifetimeReplicatedProps overridden; Super called first
[ ] DOREPLIFETIME / DOREPLIFETIME_CONDITION for each property
[ ] OnRep_ functions declared UFUNCTION() and implemented
[ ] Server RPCs have WithValidation; _Validate implemented
[ ] NetMulticast / Client RPCs guarded with HasAuthority() on call site
[ ] Subobjects registered via AddReplicatedSubObject or ReplicateSubobjects
[ ] SetOwner() called on server after spawning owned actors
[ ] DORM_DormantAll set on actors that rarely updateReplication Graph
复制图
For large player counts (50+ connections), the default net driver relevancy checks become expensive. replaces per-connection per-actor relevancy with spatial and policy-based nodes.
UReplicationGraphcpp
// Build.cs: "ReplicationGraph"
// Project: set ReplicationDriverClassName in DefaultEngine.ini
// [/Script/OnlineSubsystemUtils.IpNetDriver]
// ReplicationDriverClassName=/Script/MyGame.MyReplicationGraph
UCLASS()
class UMyReplicationGraph : public UReplicationGraph
{
GENERATED_BODY()
public:
virtual void InitGlobalActorClassSettings() override;
virtual void InitGlobalGraphNodes() override;
virtual void InitConnectionGraphNodes(UNetReplicationGraphConnection* RepGraphConnection) override;
};Key node types: (spatial), (GameState, managers), (PlayerController, PlayerState, HUD), (custom lists).
UReplicationGraphNode_GridSpatialization2DUReplicationGraphNode_AlwaysRelevantUReplicationGraphNode_AlwaysRelevant_ForConnectionUReplicationGraphNode_ActorList对于大玩家数量(50+连接),默认网络驱动的相关性检查会变得昂贵。将每个连接每个Actor的相关性检查替换为基于空间和策略的节点。
UReplicationGraphcpp
// Build.cs: "ReplicationGraph"
// Project: set ReplicationDriverClassName in DefaultEngine.ini
// [/Script/OnlineSubsystemUtils.IpNetDriver]
// ReplicationDriverClassName=/Script/MyGame.MyReplicationGraph
UCLASS()
class UMyReplicationGraph : public UReplicationGraph
{
GENERATED_BODY()
public:
virtual void InitGlobalActorClassSettings() override;
virtual void InitGlobalGraphNodes() override;
virtual void InitConnectionGraphNodes(UNetReplicationGraphConnection* RepGraphConnection) override;
};关键节点类型:(空间型)、(GameState、管理器)、(PlayerController、PlayerState、HUD)、(自定义列表)。
UReplicationGraphNode_GridSpatialization2DUReplicationGraphNode_AlwaysRelevantUReplicationGraphNode_AlwaysRelevant_ForConnectionUReplicationGraphNode_ActorListCommon Mistakes
常见错误
| Mistake | Fix |
|---|---|
Modifying state without | Add |
Server RPC without | Add |
Calling | Only call from server; guard with |
Plain | Use |
Omitting | Always call |
Passing non-replicated | Pass an ID; look up object on remote side |
Using | Use |
| Replicating cosmetic-only properties — increases bandwidth for data clients can compute locally | Only replicate gameplay-critical state; derive visuals client-side |
| 错误 | 修复方案 |
|---|---|
未使用 | 添加 |
Server RPC未使用 | 添加 |
从客户端调用 | 仅从服务器调用;使用 |
可复制组件上使用普通 | 使用 |
省略 | 始终先调用 |
在RPC参数中传递不可复制的 | 传递ID;在远程端查找对象 |
使用 | 使用 |
| 复制仅用于外观的属性 — 增加了客户端可本地计算的数据的带宽消耗 | 仅复制游戏玩法关键状态;客户端本地推导视觉效果 |
APlayerController Replication Scope
APlayerController复制范围
APlayerControllerAPawnAPlayerStateFrom :
PlayerController.hcpp
// nullptr on local players (server-side); points to the network connection otherwise
UPROPERTY(DuplicateTransient)
TObjectPtr<UNetConnection> NetConnection;UNetConnection represents a single client's network connection on the server. Each
connected client has exactly one owned by . Retrieve it
with . It is used for:
UNetConnectionUNetDriverAPlayerController::GetNetConnection()- Ownership checks: an actor's owning connection determines which client RPCs it can
receive and which properties it sees.
COND_OwnerOnly - RPC routing: Server RPCs are only accepted from the actor's owning connection.
- Detecting disconnects: bind to or check
AGameModeBase::OnLogout(orNetConnection->GetConnectionState() == USOCK_Closed) rather than pollingIsClosingOrClosed()directly.NetConnection
Use for connection-scoped Client RPCs (HUD updates, voice,
level streaming notifications). Use or for world-visible state.
APlayerControllerAPawnAPlayerStateAPlayerControllerAPawnAPlayerState来自:
PlayerController.hcpp
// nullptr on local players (server-side); points to the network connection otherwise
UPROPERTY(DuplicateTransient)
TObjectPtr<UNetConnection> NetConnection;UNetConnection 在服务器上代表单个客户端的网络连接。每个已连接的客户端都拥有一个由管理的。可通过获取它。它用于:
UNetDriverUNetConnectionAPlayerController::GetNetConnection()- 所有权检查:Actor的所属连接决定了它可以接收哪些Client RPC以及它能看到哪些属性。
COND_OwnerOnly - RPC路由:Server RPC仅接受来自Actor所属连接的调用。
- 检测断开连接:绑定到或检查
AGameModeBase::OnLogout(或NetConnection->GetConnectionState() == USOCK_Closed),而非直接轮询IsClosingOrClosed()。NetConnection
使用进行连接作用域的Client RPC(如HUD更新、语音、关卡流通知)。使用或存储世界可见的状态。
APlayerControllerAPawnAPlayerStateRelated Skills
相关Skill
- — AGameMode (server-only), AGameState / APlayerState (replicated to all), APawn net roles
ue-gameplay-framework - — GAS prediction keys, attribute set replication, GameplayEffect replication
ue-gameplay-abilities - — UPROPERTY/UFUNCTION macros, module includes
ue-cpp-foundations
- — AGameMode(仅服务器)、AGameState / APlayerState(复制到所有客户端)、APawn网络角色
ue-gameplay-framework - — GAS预测密钥、属性集复制、GameplayEffect复制
ue-gameplay-abilities - — UPROPERTY/UFUNCTION宏、模块引用
ue-cpp-foundations
Reference Files
参考文件
- — health, inventory (FFastArraySerializer), ability state, team data, subobject, dormancy, and custom relevancy patterns
references/replication-patterns.md - — Server/Client/NetMulticast decision flowchart, Reliable vs Unreliable rules, ownership routing, and common RPC mistakes
references/rpc-decision-guide.md
- — 生命值、背包(FFastArraySerializer)、技能状态、队伍数据、子对象、休眠和自定义相关性模式
references/replication-patterns.md - — Server/Client/NetMulticast决策流程图、可靠与不可靠规则、所有权路由以及常见RPC错误
references/rpc-decision-guide.md