UE4 中GameInstance、GameMode、GameState、PlayerState和PlayerController的关系

一、前言

        本篇文章为止使用的虚幻引擎版本为UE4.25.4,这几个蓝图或类是开发多人网络游戏或应用必须搞清楚和透彻的东西。学习UE4时间不长,网上找资料也没有一个说的全面的,之前一直都是半迷糊状态,通过零碎的官方文档和我找的一份比较全面的UE4资料Unreal Engine 4' Network Compendium之后再结合自己动手做的一些实验我将全面阐述这几个类的使用说明。

二、介绍

   2.1、总览

     这几个类都属属于Gameplay框架里面的,首先是官方文档的介绍我用一个表格总结如下

表2.1.1
名称 生命周期         存在的位置(服务器或客户端) 服务端和客户端是否能同步 使用方式
GameInstance 引擎启动时创建,引擎关闭后销毁或更换 都存在 不能,服务器和客户端时独立的,彼此不通信 保存特定类型的持久数据,如用户账户信息
GameMode 关卡加载时生成,销毁时一起销毁 仅在服务器 无此说法

存储客户端不需要明确知道的游戏信息,如

  • 出现的玩家和观众数量,以及允许的玩家和观众最大数量。

  • 玩家进入游戏的方式,可包含选择生成地点和其他生成/重生成行为的规则。

  • 游戏是否可以暂停,以及如何处理游戏暂停。

  • 关卡之间的过渡,包括游戏是否以动画模式开场。

GameState 同上 都存在 可以,服务器可以在GameState上使用复制变量让所有客户端保持最新的游戏数据

与所有玩家和旁观者有关、而不是与任何一个特定玩家有关的信息,如

  • 游戏已运行的时间(包括本地玩家加入前的运行时间)。

  • 每个个体玩家加入游戏的时间和玩家的当前状态。

  • 当前 Game Mode 的基类。

  • 游戏是否已开始

PlayerState 同上 都存在 同上 与一个特定玩家有关的信息,如玩家的分数、
PlayerController 同上 服务器上每个玩家都有PlayerController,但本地客户端只有本地玩家的PlayerController 客户端和服务器之间传达信息,而不必将该信息复制到其他客户端

有了这张表格的介绍就可以清晰的知道什么使用使用哪个类了,但是还是远远不够,我们还需知道每个类的生成顺序,以便在今后的使用中能获取准确的信息。比如,在生成PlayerController之后,要确定玩家的初始位置,而玩家的初始位置参数已经在关卡中提前设置好了,关卡蓝图的初始化这个时候就需要在什么类执行完之后对玩家的位置初始化。在了解这个之前还是有必要了解UE4的多人网络是如何开始的。

2.2、多人联网设置

   最容易也是最直接开始多人网络的方式是在Play按钮下设置Number of Players数为比1大的数,如图2.1.1所示,这将会自动创建一个多人网络连接。

UE4 中GameInstance、GameMode、GameState、PlayerState和PlayerController的关系_第1张图片 图2.2.1

点击图2.2.1的Advanced Setting 进入更加细化的多人联网设置,如图2.2.2所示,其中几项的说明见表2.2.1

UE4 中GameInstance、GameMode、GameState、PlayerState和PlayerController的关系_第2张图片 图2.2.2
表2.2.1
名称         描述
Luanch Separate Server 启动单独的服务器,这是一个很少使用的选项,即网络模式不需要服务器(例如独立),如果网络模式需要服务器(例如 客户端)服务器将为您启动(可能隐藏在进程内取决于在一个进程下运行)。
Play Net Mode                                 Play Offline是服务器不创建本地玩家,Play As Listen Server启动的服务器创建本地玩家、Play As Client为第一个创建的作为服务器,后面的都作为客户端
Run Under One Process 允许运行时初始化多个窗口,如果不勾选则无论Number of Players设置为多少都只有一个窗口
Number of Players 此选项定义游戏启动时其中将生成的玩家数量。编辑器和监听服务器均视为玩家,而专用服务器则不会。客户端组成剩余玩家。

2.3、连接过程

      当一个新客户端第一次连接时,会发生如下事情:

1)首先、客户端会向服务器端发送连接请求;

2)服务器端会处理这个请求,如果服务器端没有拒绝连接,就会向客户端发送一个响应(发送当前应该加载的地图、信息等);

3)服务器等待客户端加载;

4)加载完成后服务器调用本地的GameMode里的PreLogin事件,在这个事件的后续处理中还有机会拒绝连接;

5)如果服务器还是接受连接则调用GameMode中的Login事件,此事件的作用时创建一个PlayerController,然后将其复制到新连接的客户端,一旦客户端收到就会替换掉客户端临时的PlayerController,在这个过程中PlayerController的Event BeginPlay事件会被调用;

6)上面的一切都顺利后调用服务器端的GameMode的PostLogin事件。

2.4、测试的过程,各个类的Event BeginPlay事件和GameMode的PostLogin事件到底谁在前谁在后

        我分别测试了GameInstance的Init事件(这个类没有Event BeginPlay事件)、GameMode的Event OnPostLogin事件和Event BeginPlay事件、要加载关卡的Event BeginPlay事件、GameState的Event BeginPlay事件、PlayerState的Event BeginPlay事件、PlayerController的Event BeginPlay事件。得出的结果,第一次启动引擎时就执行了GameInstance的Init方法,而且设置了Number of Players为几就会执行几次这个方法。

第一次运行一个客户端时,如图2.4.1所示

UE4 中GameInstance、GameMode、GameState、PlayerState和PlayerController的关系_第3张图片 图2.4.1

这个结果跟2.3的第5个过程有冲突,2.3的第5个步骤是先执行PlayerController的Event BeginPlay事件,再执行GameMode的PostLogin事件。但是在我再键入一个新的客户端时,它的执行序列如图2.4.2所示,这个过程显然已经和2.3的第5个步骤一样了,先执行PlayerController的Event BeginPlay事件,再执行GameMode的PostLogin事件。

UE4 中GameInstance、GameMode、GameState、PlayerState和PlayerController的关系_第4张图片 图2.4.2

并且GameMode的Event BeginPlay事件不在执行了,这个让我非常困惑。

三、总结

3.1、各个类的关系有详细的说明了,唯一的遗憾时没有弄明白2.4中的问题;

3.2、再第二个玩家加入进来时,先在服务器端创建新玩家的Player State如图2.4.2所示,此时的Player State比其他类都早,此时的数据并没有同步过来,也即Player State是一个默认的对象,等到客户端生成两个Player State之后服务器端的Player State数据会保持和这生成的两个中应该对应的那个数据一致;

你可能感兴趣的:(Unreal,UE4,虚幻4,虚幻引擎,unreal)