这篇文章主要以问题的形式,针对UE同步的各个方面的内容,做一个详细而充分的讨论。对于新手理解UE的同步机制非常有帮助,对于有一定的基础而没有深入的UE程序也或许有一些启发。如果想深入了解同步的实现原理,可以参考 UE4网络同步(二)——深入同步细节
问题一:如何理解Actor与其所属连接?
附加:1. Actor的Role是ROLE_Authority就是服务端么?
问题二:你真的会用RPC么?
附加:1. 多播MultiCast RPC会发送给所有客户端么?
问题三:COND_InitialOnly怎么用?
问题四:客户端与服务器一致么?
问题五:属性同步的基本规则是?
附加:1. 结构体的属性同步有什么特别的?
问题六:组件同步的基本规则是?
Tips:同步注意的一些小细节
问题一:如何理解Actor与其所属连接?
https://api.unrealengine.com/CHN/Gameplay/Networking/Actors/OwningConnections/index.html。UE4官网关于网络链接这一块其实已经将的比较详细了,不过有一些内容没有经验的读者看起来可能还是比较吃力。
按照官网的顺序,我一点点给出我的分析与理解。首先,大家要简单了解一些客户端的连接过程。
主要步骤如下:
1.客户端发送连接请求。
2.如果服务器接受连接,则发送当前地图。
3.服务器等待客户端加载此地图。
4.加载之后,服务器将在本地调用 AGameMode::PreLogin。这样可以使 GameMode 有机会拒绝连接
5.如果接受连接,服务器将调用 AGameMode::Login该函数的作用是创建一个 PlayerController,可用于在今后复制到新连接的客户端。成功接收后,这个 PlayerController 将替代客户端的临时PlayerController (之前被用作连接过程中的占位符)。
此时将调用 APlayerController::BeginPlay。应当注意的是,在此 actor 上调用RPC 函数尚存在安全风险。您应当等待 AGameMode::PostLogin 被调用完成。
6.如果一切顺利,AGameMode::PostLogin 将被调用。
这时,可以放心的让服务器在此 PlayerController 上开始调用RPC 函数。
那么这里面第5点需要重点强调一下。我们知道所谓连接,不过就是客户端连接到一个服务器,在维持着这个连接的条件下,我们才能真正的玩“网络游戏”。通常,如果我们想让服务器把某些特定的信息发送给特定的客户端,我们就需要找到服务器与客户端之间的这个连接。这个链接的信息就存储在PlayerController的里面,而这个PlayerController不能是随随便便创建的PlayerController,一定是客户端第一次链接到服务器,服务器同步过来的这个PlayerController(也就是上面的第五点,后面称其为拥有连接的PlayerController)。进一步来说,这个Controller里面包含着相关的NetDriver,Connection以及Session信息。
对于任何一个Actor(客户端上),他可以有连接,也可以无连接。一旦Actor有连接,他的Role(控制权限)就是ROLE_AutonomousProxy,如果没有连接,他的Role(控制权限)就是ROLE_SimulatedProxy 。
那么对于一个Actor,他有三种方法来得到这个连接(或者说让自己属于这个连接):
1.设置自己的owner为拥有连接的PlayerController,或者自己owner的owner为拥有连接的PlayerController。也就说官方文档说的查找他最外层的owner是否是PlayerController而且这个PlayerController拥有连接。
2.这个Actor必须是Pawn并且Possess了拥有连接的PlayerController。这个例子就是我们打开例子程序时,开始控制一个角色的情况。我们控制的这个角色就拥有这个连接。
3.这个Actor设置自己的owner为拥有连接的Pawn。这个区别于第一点的就是,Pawn与Controller的绑定方式不是通过Owner这个属性。而是Pawn本身就拥有Controller这个属性。所以Pawn的Owner可能为空。 (Owner这个属性在Actor里面,蓝图也可以通过GetOwner来获取)
对于组件来说,那就是先获取到他所归属的那个Actor,然后再通过上面的条件来判断。
我这里举几个例子,玩家PlayerState的owner就是拥有连接的PlayerController,Hud的owner是拥有连接的PlayerController,CameraActor的owner也是拥有连接的PlayerController。而客户端上的其他NPC(一定是在服务器创建的)是都没有owner的Actor,所以这些NPC都是没有连接的,他们的Role就为ROLE_SimulatedProxy。
所以我们发现这些与客户端玩家控制息息相关的Actor才拥有所谓的连接。不过,进一步来讲,我们要这连接还有什么用?好吧,照搬官方文档。
<连接所有权是以下情形中的重要因素:
1.RPC需要确定哪个客户端将执行运行于客户端的 RPC
2.Actor复制与连接相关性
3.在涉及所有者时的 Actor 属性复制条件