云计算百科
云计算领域专业知识百科平台

虚幻引擎DS服务器(专用服务器)初步搭建及简单数据同步应用(二)

前置

虚幻引擎DS服务器(专用服务器)初步搭建及简单数据同步应用(一)-CSDN博客icon-default.png?t=O83Ahttps://blog.csdn.net/qq_48223371/article/details/143127490?spm=1001.2014.3001.5501

数据同步

前置知识

关于数据同步,这里有两个前置的知识,一个是关于UE的存档系统,一个是UE的属性复制及远程调用。

虚幻引擎中的RPC | 虚幻引擎 5.5 文档 | Epic Developer Community (epicgames.com)icon-default.png?t=O83Ahttps://dev.epicgames.com/documentation/zh-cn/unreal-engine/remote-procedure-calls-in-unreal-engine

RPC

无论是属性复制还是RPC,都要求Actor本身设置为Replicates(复制)

事件类型

类型

说明

NotReplicated

默认值,表示该事件不进行复制。

RunOnServer

通常在拥有目标所有权的客户端上调用,则事件将在服务器上运行。这是客户端向服务器发送数据的主要方法。如果从服务器调用该事件,则仅在该服务器上运行。

RunOnOwningClient

一般在服务器调用,则该事件将在拥有目标Actor的客户端上运行。特别地:如果服务器可以拥有Actor本身,则在服务器上运行。如果从客户端调用,则仅在调用该事件的客户端上运行。

Multicast

如果在服务器上调用组播事件,则该事件将复制到所有连接的客户端,无论拥有目标对象的是哪个连接。如果客户端调用组播事件,该事件会被视为未复制,并仅在调用该事件的客户端上运行。

如上图,我们可以看到,GameMode只存在于服务器上,所以在GameMode上写的事件都会在服务器自动执行。

上图PP事件并未设置在服务器执行

1)GameInstance:服务器和每个客户端上都存在一个独立的GameInstance,这些实例彼此不通信。保存着特定类型的持久数据。与USaveGame配合可将数据序列化到本地文件。

2)GameMode:只存在于服务器,用于设定游戏规则。

3)PlayerController:每个客户端有自己的PlayerController,它们在服务器和关联的客户机之间进行复制,但不会复制到其他客户端。服务器可以获取所有玩家的PlayerController。

4)GameState:存在于服务器和客户端上,因此服务器可以在GameState上使用变量复制让所有客户端保持最新的游戏数据,复制的过程是自动进行的。通常是服务器上改变变量的值,客户端的值就会相应的改变。一般存储游戏中共有的数据。

5)PlayerState:服务器和客户端上存在与游戏相连的每个玩家的PlayerState,所有玩家的PlayerState存在于所有机器上。存储玩家相关的数据,可以自由复制进行同步。

6)Pawn:Pawn(包括Character)也存在于服务器和所有客户端上,可以包含复制变量和事件。

Network Role

Network Role

说明

None

Actor在网络游戏中无角色,不会复制。

Authority

服务器或者单机游戏的客户端中,Actor的Role都为Authority。表示有完全控制权。

Simulated Proxy

只有模拟权,例如Client1中的Pawn2和Client2中的Pawn1。只是单纯把服务器的状态同步下来,无法直接改变其状态。

Autonomous Proxy

自治权,一方面把服务器状态同步过来,另一方面能通过一些方式(属性同步和RPC)去改变服务器上的状态,再同步回自身。例如Client1中的Pawn1,Client2中的Pawn2。

注:对于玩家的Network Role主要是用于区分不同的玩家,在同一个客户端中可能会有多个网络角色,网络角色可以让我们特定的角色去执行相应的事件,但值得注意的是,Network Rolee在Actor创建之初,可能并未正确指定,因此在Actor刚刚创建的时候,例如构造函数中或者BeginplayEvent中,获取的Network Role可能是不正确的;另一方面可以用更常规的做法:IsServer函数(当前是否是服务器)和IsLocallyControlled(是否是被本地拥有控制)(也应避免在构造函数中使用)去确定玩家角色。一般在多人游戏中(服务器与客户端不在一起)的本地玩家只有自治权,其他的同步过来的玩家都是模拟权。

属性复制

在每一个actor的属性变量的细节面板都有一个选项

选项

说明

None

默认值,不网络同步

Replicated

设置后,在服务器修改此值,会自动同步到客户端,但是有一定时间延迟。

RepNotify

设置后,在服务器修改此值,会自动同步到客户端,但是有一定时间延迟。同时会自动调用回调函数。

注:RepNotify 也可以在非网络同步时使用,用于在变量更改时进行的一些关联操作。例如我们在更改一些数据后可能有后续的UI变化,重新绘制等操作,这些操作会在变量更改后自动执行。如果变量设为RepNotify,函数列表会自动多出一个回调函数,函数以OnRep_变量名为名称。

同步开发

存档

我们进行数据同步之前应该有一套存档系统用于读取与存储数据,将数据持久化。(可能看到这的人也不是初学者了,存档系统就不会太详细讲述)

首先我们创建一个SavegGame的蓝图类,再创建一个蓝图接口,一个游戏实例,一个GameMode

在蓝图接口中创建用于加载和保存存档的函数声明,使用接口的目的是不需要频繁的去Castto,这个也是要消耗性能,还是能优化就优化。

其中GetSaveGame有一个返回值,返回我们创建的SaveGame对象。

在游戏实例中写入以下蓝图,实现加载及保存存档对象。

接着我们关于存档的操作就是简单的加载,保存,获取。

至此,我们一个简单的存档系统就做好了,这个存档系统使用方便,可扩展性好,大家可以根据自己的需求自行扩展。

服务器

首先我们使用服务器进行数据同步,数据应该是存在于服务器端,而并非客户端。所以我们的存档系统也应该是在服务器端去操作。基于此,我们的加载及保存逻辑就写在GameMode中,因为GameMode只存在于服务器端。

接下来我们创建一个GameStateBase的蓝图类

上面我们说过,GameState在服务器和客户端每一个都有一个,数据会自动同步(勾选属性复制)。

注意:GameState只能存储游戏的公共数据,对于玩家的私人数据使用PlayerState进行存储和同步,例如不同玩家的当前等级和当前血量等。

在GameState创建一个变量。并将变量设置为复制

在第三人称蓝图中创建事件,用于设置及同步数据,这里为了方便,我就不写接口了,理论上是需要接口去获取值。

我们在设置GameState中的数据时,只能使用RunOnServer事件,因为数据的同步是单向的,所以数据的操作要在服务器进行。

为了便于测试,我们创建一个Actor,用来检测碰撞,并打印出GameState的值,看看是否同步。

上述红框的蓝图是用于检测玩家是否是本机控制的玩家,也可以使用IsLocallyControlled(是否是被本地拥有控制)来判断

在第三人称蓝图中创建事件

我这里的事件用的在拥有的客户端执行的类型,但是在触发前我进行了筛选,实际上我们这里可以选择不复制。

最后GameState里面的数据可以通过接口同步给游戏实例,进而用来存档。最后会变成这样

注:一般我们只会在结束时保存,在运行期间一般是不会进行保存的,只进行同步,除非有特殊要求,比如自动存档啥的,但是自动存档一般也是单机游戏用的多,网络游戏几乎没有。当然这里是GameState,如果是PlayerState,可能当玩家断开连接的时候或者其他情况就需要去进行保存了。

到此同步基本结束。

运行结果

总结

我们在数据同步的过程中其实并没有用到太多的RPC的地方,因为虚幻内置的数据同步已经将我们大部分的同步过程省略掉了,我们需要做的仅仅是确定数据什么时候加载以及数据如何更新,RPC使用更多的地方是在我们开发过程中的一些功能逻辑中,我们更多的是考虑我们的业务逻辑而并非数据同步过程。在业务逻辑中,RPC的调用是非常多而且很容易出错,需要我们充分理解每个RPC的含义。

另外,数据同步包括存档系统是无法同步和保存对象类型的变量的,只能是除对象类型之外的数据类型。不过据说C++是可以同步对象类型的,我还没有试,大家可以试试。

Tips

关于虚幻引擎我个人有一个小的语言设置,在编辑器偏好设置中,

人生有两个悲剧,第一是想得到的得不到,第二是想得到的得到了。

赞(0)
未经允许不得转载:网硕互联帮助中心 » 虚幻引擎DS服务器(专用服务器)初步搭建及简单数据同步应用(二)
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!