UE4 C++网络编程基础知识总结
Posted Tanzq*
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UE4 C++网络编程基础知识总结相关的知识,希望对你有一定的参考价值。
角色类型
每个Actor都存在两个属性来判断当前的Actor在 服务器 / 客户端上的身份类型:
Role: 判断当前角色在本地端的身份类型。
RemoteRole:判断当前角色在远端身份类型(当是客户端时,远端为服务端,当是服务端时,远端是客户端)。
网络角色类型:
Simulated : 由服务器进行数据发送,当前终端进行操控模拟。操控来源于服务器。
Autonomous: 由当前终端实例进行操控。操控来源于真人。
Authority:服务器端存在标记,表明当前Actor存在于服务器。
- Role 类型分布
Simulate | Autonomous | Authority | |
---|---|---|---|
服务器 | 不存在 | 不存在 | 服务器拥有复制权限的权威性 |
客户端 | 服务器在当前引擎实例中模拟的玩家角色 | 当前引擎实例中由真人操控的角色 | 不存在 |
Role 可以用来清晰的裁定当前角色是否在服务器,一般HasAuthority就是检查此变量。
我们也可以用来裁定当前对象是否有权发动RPC。Simulate对象无法执行RPC函数。
- RemoteRole类型分布
Simulate | Autonomous | Authority | |
---|---|---|---|
服务器 | 当前Actor在远端是模拟的身份 | 当前Actor自主权操控权在远端 | 不存在 |
客户端 | 不存在 | 不存在 | 拥有当前Actor复制权限的权威性 |
RemoteRole可以用来裁定当前Actor另一端的身份类别。如果由服务器构建的对象,则远端均是Simulate。
Remote Procedure Call (RPC)
RPC,远程调用,指在本机上调用函数,但在其他机器上远程执行函数。RPC函数可以允许客户端或服务器通过网络连接相互发送消息。
RPC执行分三种形式:
- 服务端执行(Server) : 在客户端上调用,在服务器端执行
- 客户端执行(Client): 在服务器端调用,在客户端执行
- 所有终端执行(Multicast):在服务器端调用,在所有终端执行
C++ 实现:
函数说明符 | 效果 |
---|---|
Server | 此函数仅在服务器上执行。用于声明名称与主函数相同的附加函数,但是末尾添加了_Implementation ,是写入代码的位置。必要时,此自动生成的代码将调用 _Implementation 方法。 |
Client | 此函数仅在拥有在其上调用此函数的对象的客户端上执行。用于声明名称与主函数相同的附加函数,但是末尾添加了Implementation 。必要时,此自动生成的代码将调用Implementation 方法。 |
NetMulticast | 此函数将在服务器上本地执行,也将复制到所有客户端上,无论该Actor的 NetOwner 为何。 |
Reliable | 此函数将通过网络复制,并且一定会到达,即使出现带宽或网络错误。仅在与Client 或Server 配合使用时才有效。 |
Unreliable | 此函数将通过网络复制,但是可能会因带宽限制或网络错误而失败。仅在与Client 或Server 配合使用时才有效。 |
WithValidation | 用于声明名称与主函数相同的附加函数,但是末尾需要添加_Validate 。此函数使用相同的参数,但是会返回bool ,以指示是否应继续调用主函数。 |
服务端执行:
- 函数声明
UFUNCTION(BlueprintCallable, Server, Reliable, WithValidation, Category = "ALS|Character States")
void Server_SetDesiredGait(EALSGait NewGait);
- 函数实现
bool AALSBaseCharacter::Server_SetDesiredGait_Validate(EALSGait NewGait)
// 这里写服务器进行检测的逻辑
return true;
void AALSBaseCharacter::Server_SetDesiredGait_Implementation(EALSGait NewGait)
// 这里写你的逻辑
SetDesiredGait(NewGait);
客户端执行:
- 函数声明
UFUNCTION(BlueprintCallable, Client, Reliable, Category = "ALS|Character States")
void Client_SetDesiredGait(EALSGait NewGait);
- 函数实现
oid AALSBaseCharacter::Client_SetDesiredGait_Implementation(EALSGait NewGait)
// 这里写你的逻辑
所有终端执行 :
- 函数声明
UFUNCTION(BlueprintCallable, NetMulticast, Reliable, Category = "ALS|Character States")
void NetMulticast_SetDesiredGait(EALSGait NewGait);
- 函数实现
void AALSBaseCharacter::NetMulticast_SetDesiredGait_Implementation(EALSGait NewGait)
// 这里写你的逻辑
RPC 调用注意事项 :
- 它们必须从Actor上调用
- Actor必须被复制。
- 如果RPC是从服务器调用并在客户端上执行,则只有实际拥有这个Actor的客户端才会执行函数。
- 如果RPC是从客户端调用并在服务器上执行,客户端就必须拥有调用RPC的Actor。
- 多播RPC则是个例外: ① 如果他们是从服务器调用,服务器将在本地和所有已连接的客户端上执行它们。 ②如果它们是从客户端调用,则只在本地而非服务器上执行。③ 多播事件限制机制:在特定的Actor的网络更新期内,多播函数将不会复制两次以上。
RPC调用情况分析
- 从服务器调用的 RPC
Actor 所有权 | 未复制 | NetMulticast | Server | Client |
---|---|---|---|---|
Client-owned actor | 在服务器上运行 | 在服务器和所有客户端上运行 | 在服务器上运行 | 在 actor 的所属客户端上运行 |
Server-owned actor | 在服务器上运行 | 在服务器和所有客户端上运行 | 在服务器上运行 | 在服务器上运行 |
Unowned actor | 在服务器上运行 | 在服务器和所有客户端上运行 | 在服务器上运行 | 在服务器上运行 |
- 从客户端调用的 RPC
Actor 所有权 | 未复制 | NetMulticast | Server | Client |
---|---|---|---|---|
Owned by invoking client | 在执行调用的客户端上运行 | 在执行调用的客户端上运行 | 在服务器上运行 | 在执行调用的客户端上运行 |
Owned by a different client | 在执行调用的客户端上运行 | 在执行调用的客户端上运行 | 丢弃 | 在执行调用的客户端上运行 |
Server-owned actor | 在执行调用的客户端上运行 | 在执行调用的客户端上运行 | 丢弃 | 在执行调用的客户端上运行 |
Unowned actor | 在执行调用的客户端上运行 | 在执行调用的客户端上运行 | 丢弃 | 在执行调用的客户端上运行 |
数据同步
Actor必须满足在网络上被复制,设置的参数需要开启复制,参数的修正必须在服务器端被修改,才可以在网络上进行同步。
蓝图参数同步有两种方式 : Replicated, RepNotify
- Replicated, 同步数据,但没有通知, 无法直接通过参数修改驱动逻辑
- RepNotify, 同步数据,并生成通知,进行更新通知(向所有终端通知,满足相关性)
属性标签 | 效果 |
---|---|
Replicated | 属性应随网络进行复制。 |
ReplicatedUsing=FunctionName | ReplicatedUsing 说明符指定一个回调函数,其在属性通过网络更新时执行。(向除去服务器外的所有终端进行通知。) |
属性复制条件
属性复制被注册后, 无法进行取消。所有属性默认的复制条件是:不发生变化不进行复制。我们可以使用UE提供的条件进行修正,通过条件的约束设定可以有效的节约网络带宽。
条件 | 说明 | 事例 |
---|---|---|
COND_InitialOnly | 该属性仅在初始数据组尝试发送 | 玩家的名字等 |
COND_OwnerOnly | 该属性仅发送至 actor 的所有者 | 手持武器子弹剩余数量等 |
COND_SkipOwner | 该属性将发送至除所有者之外的每个连接 | |
COND_SimulatedOnly | 该属性仅发送至模拟 actor | FPS自己只需要看到手臂,但其他玩家需要看到自己的整个身体等 |
COND_AutonomousOnly | 该属性仅发送给自主 actor | |
COND_SimulatedOrPhysics | 该属性将发送至模拟或 bRepPhysics actor | |
COND_InitialOrOwner | 该属性将发送初始数据包,或者发送至 actor 所有者 | |
COND_Custom | 该属性没有特定条件,但需要通过 SetCustomIsActiveOverride 得到开启/关闭能力 |
C++ :
UPROPERTY(BlueprintReadOnly, Replicated, Category = "ALS|Ragdoll System")
FVector TargetRagdollLocation = FVector::ZeroVector;
UPROPERTY(BlueprintReadOnly, Category = "ALS|State Values", ReplicatedUsing = OnRep_RotationMode)
EALSRotationMode RotationMode = EALSRotationMode::LookingDirection;
绑定参数到复制参数列表:
virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
void AALSBaseCharacter::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
Super::GetLifetimeReplicatedProps(OutLifetimeProps);
DOREPLIFETIME(AALSBaseCharacter, TargetRagdollLocation);
DOREPLIFETIME_CONDITION(AALSBaseCharacter, RotationMode, COND_SkipOwner);
需要使用属性复制条件进行优化就使用:DOREPLIFETIME_CONDITION
,不需要就使用:DOREPLIFETIME
。
网络关联性
UE网络模块考虑到通信带宽问题,针对场景中的所有Actor数据更新制定了高效的同步方案,根据Actor的网络关联性,进行数据更新,这样可以有效的规避无用数据更新造成的通信带宽压力。
网络关联性约束了Replicated是否进行广播,约束关系受限于关联性规则。
关联性用途:用来解决同步过程中,无关数据的传递带宽压力,用来筛选有意义内容进行同步,表现同步信息是否同步给目标。
关联性规则:
- AlwaysRelevant, 相关性最大,勾选之后,所有终端永远会收到此Actor同步信息,例如烟雾弹。
- NetUseOwnerRelevancy, 如果有拥有者Owner,则使用所有者的相关性(包括剔除距离约定)。此检查在第一项之后完成。例如角色拾取枪支。
- OnlyRelevantToOwner, 只与当前所有者相关,同步数据只发给所有者,不发送任何人,没有所有者不同步。
- Actor 出现依 附关系,则关联性取决于基础的Actor相关性。
- 如果Actor不可见(bHidden = true )并且 Root Component 没有碰撞,则不具备相关性。
- 采集距离(Net Cull Distance Squared)在采集范围内具备关联性。
- 约束层级关系(如果RPC勾选了Reliable则关联性设置失效)
以上是关于UE4 C++网络编程基础知识总结的主要内容,如果未能解决你的问题,请参考以下文章