目录
UE4-多人游戏中物体位置同步的三种方式
位置同步需求与问题
- 非Character类,因为Character类中有CharacterMovement组件,这个组件已经在内部实现好了角色的位置同步;
- 玩家自建的Pawn在游戏中可以通过WASD在网络中实现位置同步,即玩家A能看到玩家B的运动;玩家B也能看到玩家A的运动;
- 因为要控制移动,所以要绑定轴事件,来进行持续控制;
UE4网络和多人游戏概述
首先概述一下UE4中的网络和多人游戏,网络多人游戏中,UE4使用C/S架构。即一台机器作为server并且主持一次多人游戏的会话。其他玩家将会作为client连接到这台server。server然后与每一个连接着的client分享游戏状态信息并且为他们提供互相通信的机会。最重要的一点是,UE4的服务器端对整个游戏拥有最大的权限。服务器才是多人游戏真正运行的地方。各个client远程控制着一个Pawn,client在server中仅仅对这个Pawn拥有权限。然后发送RPC(远程调用)来操作Pawn,server也不是直接将画面传回client,而是Replicate游戏的状态信息到每个client然后进行更新。所以RPC、Replication是UE4网络同步的关键点。
Replication
变量可以在网络之间复制。游戏中的变量在server进行修改然后同步到各个client。在client定义变量并且修改会导致作弊的现象发生。Replication有两种方式,一个是Replicated方式,一个是RepNotify方式。将变量设置为Replicated,这个操作表明server将会产生一个变量的副本并复制到client。可以使用RepNotify变量,在变量更新时进行复制同步。
与Replication不同的是,RepNotify仅在变量更新时在本地触发,这使其成为一种低开销的方式来触发游戏逻辑,以响应Actor(Authority)上的变量更改。与使用RPC或Replication相比,RepNotify更为可取,因为可以将它们添加到需要复制而与其他游戏功能无关的变量中,从而节省大量带宽。
RPCs
RPC(远程过程调用)是在本地调用但在另一台计算机上远程执行(与调用计算机分开)的函数。RPC功能非常有用,它允许client或server通过网络连接相互发送消息。这些功能主要用来执行不可靠的事件。例如播放声音,产生粒子特效或其他的对Actor的功能不重要的临时效果。
RPCs(远程方法调用)中有四种可选方式:NotReplicated(不复制)、Multicast(多播)、RunOnServer(在服务器运行)、RunOnClient(在客户端运行)。在不同的地方使用不同的方式调用会产生不同的效果(参考UE4官方文档)
同步方式一:单纯RPCs
(以旋转为例)单纯的使用RPCs来进行位置同步的实现:先RunOnServer再Multicast。为什么这么做是因为,Client的自定义事件通过RunOnServer将会在Server执行。然后在server处Multicast,这样所有client都能收到并更新位置。但这一种方式可能会遇到同步位置不精确的问题,因为毕竟AddLocalRotaion这个函数只是增加局部旋转,转多转少跟机器性能相关。正像上面提到的,RPC做的是瞬间的不可靠的事情。
同步方式二:RPCs+Replication
使用RPCs+Replication实现位置的同步:还是先RunOnServer再Multicast。在这里设置变量为Replication主要是为了位置的精确性而考虑,虽然大致步骤相同。与上边不同的是,在RunOnServer这一过程中,我们的运动是在Server上的,并且在Server上获得了运动的值并且set到了需要同步的变量CurrentRot之中。在Multicast时,各个端的物体将会以该CurrentRot作为标准进行SetWorldRotation。这样保证了位置的准确性,但是Replication一直在同步,消耗网络性能。
同步方式三:RPCs+RepNotify
使用RPCs+RepNotify实现位置的同步:RunOnServer即可。新建CurrentRotation变量并将其设置为RepNotify,设置完成后会多出一个函数OnRep_CurrentRotation。在CurrentRotation的值发送变动时才会触发该函数执行逻辑。(详情可参考UE4官方文档的RepNotify射击案例)。第一步将运动的动作在Server上执行,Server执行后动作发生改变并赋值给CurrentRotation变量,CurrentRotation发生改变则会调用OnRep_CurrentRotation函数进行对其他端actor位置的设置,在此函数中使用了SwitchHasAuthority函数进行判断,对Remote的Pawn进行位置设置,道理与Multicast相似,但是更可靠,效率也更高。(这个Authority是相对的,你的客户端上的Pawn在服务器上托管,那服务器对此托管的Pawn就具有Authority)。