Example and Usage
虽然PlayerController是网络中最重要的类之一,但默认情况下它没有太多功能。所以我们创建一个小例子,搞清楚它为什么必须。在所有权一章节中,你会知道为什么PlayerController比RPC还要重要。接下来的例子会告诉你如何使用PlayerController通过一个界面按钮使GameState的一个复制变量自增。
为什么我们需要PlayerController?
好了,我不想在这写RPC和拥有权的内容。所以只是简单解释:即使属于客户端,控件也只存在于客户端/监听服务器上,在服务器上也没有服务器RPC实例去运行。因为它根本没有被复制!
这意味着我们需要一个方法以供在服务器调用,按下一个按钮使变量自增。
为什么不直接调用GameState上的RPC呢?因为GameState属于服务器。
服务器RPC需要客户端持有!
(这段意思应该是,如果没有PlayerController类的话,客户端无法用服务器RPC通知服务器,GameState上的RPC也因为没有客户端持有所以无法响应对应操作)
Blueprint
首先,我们需要一个按钮部件。希望你应该会创建!
这些图我倒转顺序来发,这样你就可以知道它什么时候结束和它前面被哪些事件调用。
由GameState开始。
是一个用于复制变量自增的事件:
这个事件是在服务器这边调用的,在我们服务器rpc内部的PlayerController:
最后,我们用我们的按钮调用服务器RPC:
当我们在客户端点击这个按钮部件的时候,我们通过客户端的PlayerController里的服务器RPC通知服务器,然后调用GameState的‘IncreaseVariable’事件去使复制变量自增。
由于自增的这个变量是replicated属性的,所以会更新所有GameState实例,客户端上也能看到这个更新!
这个例子的C++版本,我会用PlayerController的BeginPlay事件来取代按钮部件按下。这基本没什么影响,主要是在C++里面实现窗口部件需要很多代码而且与这些代码和网络主题无关!
(简单提及一下,server_increaseVariable就是服务器RPC,客户端拥有,用来调用服务器上的函数,所以有了最下面这个判断if(Role<ROLE_Authority),确保这是客户端调服务器RPC。而这个服务器RPC实现的功能就是通知GameState调用变量自增函数。然后当变量变化了之后,客户端同样会更新这个变量的新状态,因为这个变量被注册成replicated属性了)
这是一些代码,如果你还不懂他们的用法,不用担心。接下来的章节会帮助你理解。
AHUD类只在每个客户端上可用,他可以通过PlayerController进行访问。它会自动生成。
在UMG发布之前,HUD用于在客户端上绘制文本、纹理等等。
到目前为止,widgets部件大部分取代了HUD类。
但你仍然可以用HUD类来调试,或者使用一个独立区域来生成、显示、隐藏和销毁widgets部件。
因为HUD没有直接联网,例子只能展现单玩家功能,所以直接跳过了。
(HUD类其实现在基本不用了)
UMG部件
UMG用于虚幻新UI系统。
继承自Slate类,Slate类是使用C++创建UI的基类,他也是UE4里面UMG视图自身创建的基类。
UMG只在本地客户端有效(监听服务器)。
UMG没有replicated属性,你如果需要进行replicated操作(例如按按钮发生一些事情),那么你需要另外独立的可复制的类来帮助实现。
为了帮助学习UMG,你登录https://docs.unrealengine.com/latest/INT/API/Runtime/UMG/index.html去查API。
在上面APawn类的示例中,我使用了UMG了,这里就不写例子了。
Dedicated vs Listen Server(专用服务器vs监听服务器)
专用服务器
专用服务器是不需要客户端的独立服务器。
它与游戏客户端分开运行,主要用于玩家可以随时进入/离开。
专用服务器可以在Windows和Linux系统编译,或运行在虚拟服务器上,玩家可以通过固定ip地址连接到这些服务器。
专用服务器没有可视化内容,所以他们不需要UI界面,而且没有PlayerController类。在游戏中也没有Character或者类似Character的东西。
监听服务器
监听服务器也是客户端。
意味着,服务器至少拥有一个客户端相连。
这个客户端被称为监听服务器,如果他断开连接,那么服务器也会关闭。
因为同样作为客户端,监听服务器需要UI和PlayerController。
在监听服务器上调用‘PlayerController(0)’会返回该客户端的PlayerController。
由于监听服务器运行与客户端自身上,所以其他人通过IP连的也是客户端。
相比于专用服务器,这会有个问题,就是用户没有静态IP。
但使用OnlineSubsystem(稍后解释),动态IP问题可以得到解决。