UE4 C++联网RPC教程笔记(三)(第8~9集)完结
8. exe 后缀实现监听服务器
前面我们通过蓝图节点实现了局域网连接的功能,实际上我们还可以给项目打包后生成的 .exe 文件创建一个快捷方式,然后修改这个快捷方式的属性中的目标就可以实现简易的联网功能。
下面内容截取自梁迪老师准备的 RPC 联网文档:
使用 .exe 后缀输入和 open IP 地址联网
注意:这里只讨论 NM_Standalone、NM_ListenServer 以及 NM_Client 的情况
- NM_Standalone:打包出 exe 后,不创建快捷方式直接运行 exe,执行
GetNetMode()
返回 NM_Standalone 类型,在这个状态下打印GetWorld()->IsServer()
以及HasAuthority()
都是 true,如果在存在监听服务器的情况下,运行命令行open 127.0.0.1
,该单独端就会链接上监听服务器,执行GetNetMode()
返回 NM_Client 类型,打印GetWorld()->IsServer()
以及HasAuthority()
都是 false,如果再次运行命令行open 127.0.0.1
,该端会先断开服务器,然后再链接一次 - NM_ListenServer:打包出来的 exe 生成快捷方式,并且在快捷方式的属性下在 exe 结尾添加
(空格)?listen
,如:RPCProject.exe ?listen
,运行该快捷方式就会运行监听服务器端,执行GetNetMode()
返回 NM_ListenServer 类型,打印GetWorld()->IsServer()
以及HasAuthority()
都是true,如果运行命令行open 127.0.0.1
,该监听服务器端就会变成单独端 NM_Standalone - NM_Client:打包出来的 exe 生成快捷方式,并且在快捷方式的属性下在 exe 结尾添加
(空格)127.0.0.1 -game
,如:RPCProject.exe 127.0.0.1 -game
,运行该快捷方式,如果存在监听端,就会链接上监听服务器,成为客户端,执行GetNetMode()
返回 NM_Client 类型,打印GetWorld()->IsServer()
以及HasAuthority()
都是 false
接下来我们在 GameMap 里用到的玩家控制器中添加一些打印当前端的逻辑。
RPCController.h
protected:.
void EchoNetMode();
RPCController.cpp
// 引入头文件
#include "RPCHelper.h"
void ARPCController::BeginPlay()
{
Super::BeginPlay();
// 限定打开的窗口尺寸。此处老师将变量名拼写错成 “Src”
FString ScreenCommand = FString("r.setres 1280x720w");
ConsoleCommand(ScreenCommand);
bShowMouseCursor = false;
FInputModeGameOnly InputMode;
SetInputMode(InputMode);
// 打印当前的端
EchoNetMode();
}
void ARPCController::EchoNetMode()
{
ENetMode NetMode = GetNetMode();
switch (NetMode)
{
case NM_Standalone:
DDH::Debug() << "NM_Standalone" << DDH::Endl();
break;
case NM_DedicatedServer:
DDH::Debug() << "NM_DedicatedServer" << DDH::Endl();
break;
case NM_ListenServer:
DDH::Debug() << "NM_ListenServer" << DDH::Endl();
break;
case NM_Client:
DDH::Debug() << "NM_Client" << DDH::Endl();
break;
case NM_MAX:
DDH::Debug() << "NM_MAX" << DDH::Endl();
break;
}
}
编译后,将默认关卡设置为 GameMap。随后开始打包。
打包成功后,运行 .exe 文件,可以看到左上角打印了当前的端名以及控制器名。
创建 .exe 文件的一个快捷方式,命名为 RPCCourseServer (保留 .exe 后缀),随后修改该文件的属性。
运行 RPCCourseServer.exe,可以看到左上角已经变成了聆听服务器。
再创建一个快捷方式,命名为 RPCCourseClient,这次给属性里的目标添加后缀 (空格)127.0.0.1 -game
。先运行 RPCCourseServer,然后再运行 RPCCourseClient.exe,可以看到后者的窗口里左上角显示是客户端。
此时在服务端按下 J 键,只有在客户端能看到角色处生成了红色的数字 1。说明联网方法和变量都是可以用的。
关掉客户端,服务端左上角会显示客户端的控制器登出了。
保持服务端开启,运行 RPCCourse.exe,按 ~
键(波浪符)呼出控制台,输入 open 127.0.0.1
。可以看到独立端加入了服务端,并且原独立端左上角输出了当前为客户端。
此时在服务端按下 J 键,也是只有原独立端可以看到自己角色位置生成了一个红色的数字 1。
在服务端呼出控制台然后输入 open 127.0.0.1
,服务器会关闭。
9. C++ 实现监听服务器
前面我们用蓝图和快捷方式实现聆听服务器联机,接下来我们尝试下用 C++ 来实现同样的效果。下面内容截取自梁迪老师准备的 RPC 联网文档:
创建寻找加入会话 C++ 模式(这里只实现局域网)
C++ 联网步骤和蓝图基本相同,但是中间多了一个 StartSession()
方法需要调用,主要可以参考
- UCreateSessionCallbackProxy
- UStartSessionCallbackProxy
- UFindSessionsCallbackProxy
- UJoinSessionCallbackProxy
- UDestroySessionCallbackProxy
这些类的实现,具体实现参考项目里的 URPCInstance 类。
UE4 官方推荐将联网的逻辑放在 GameInstance 下处理,GameInstance 在整个游戏所有关卡中都存在,用来传递关卡数据,在保存数据方面起作用,联网数据放在 GameInstance 下方便在任何关卡去操作联网
接下来开始实操。在默认路径下创建一个 C++ 的 Instance 类,命名为 RPCInstance。
将默认地图设置成 MenuMap。
来到主界面 UI 类,声明一个 URPCInstance 的指针和相应的注册方法,用来保存对 GameInstance 的引用,并且声明两个蓝图可调用的方法用于接入主界面的按钮点击事件。
MenuWidget.h
// 提前声明
class URPCInstance;
UCLASS()
class RPCCOURSE_API UMenuWidget : public UUserWidget
{
GENERATED_BODY()
public:
void AssignRPCInstance(URPCInstance* InInstance);
UFUNCTION(BlueprintCallable)
void LANServerEvent();
UFUNCTION(BlueprintCallable)
void LANClientEvent();
public:
URPCInstance* RPCInstance;
};
MenuWidget.cpp
// 引入头文件