[UE4]自定义服务器

UE4 dedicated server是一个很好的游戏服务器,但是对于大厅和聊天服务器来说,我们要自行开发,通过UE4的socket组建很方便的和其他服务器建立连接

创建Socket

FSocket* Socket = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateSocket(NAME_Stream, TEXT("default"), false);

CreateSocket参数

  1. 类型
  2. 描述
  3. 是否强制UDP

设置地址

FString address = TEXT("127.0.0.1");
int32 port = 19834;
FIPv4Address ip;
FIPv4Address::Parse(address, ip);


TSharedRef addr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();
addr->SetIp(ip.GetValue());
addr->SetPort(port);

连接服务器

bool connected = Socket->Connect(*addr);

如果返回True说明连接服务器成功.

发送消息


FString serialized = TEXT("loadPlayer|1");
TCHAR *serializedChar = serialized.GetCharArray().GetData();
int32 size = FCString::Strlen(serializedChar);
int32 sent = 0;

发送内容FString转换成TCHAR*,格式化发送数据

bool successful = Socket->Send((uint8*)TCHAR_TO_UTF8(serializedChar), size, sent);

接受数据我们用到 HasPendingData 和Recv 函数在 FSocket 类中.

在工程中引用Sockets模块

PublicDependencyModuleNames.AddRange(
   new string[]
   {
      "Core",
      "CoreUObject",
      "Engine",
      "Sockets"
   }
);

UE4 架构在构建时就充分考虑了多人游戏因素。只要您遵守基本的架构原则,通常就无需太费事即可将单人游戏体验扩展为多人游戏。

UE4 网络连接是基于服务器/客户端模式构建。也就是说,这个模式中有一个担当主控(authoritative)的服务器端(做出所有重要决定),用于确保所有连接的客户端可以持续更新,以便其持续获得服务器环境的最新近似复本。

Actor

在单人游戏体验中,actor 被用于呈现游戏世界。而在多人游戏中,这一点丝毫没有变化,只不过客户端将获得每个 actor 的近似复本,而服务器将保持主控(authoritative)版本。

Actor 是服务器让客户端保持最新的主要途径。当服务器需要更新特定的客户端时,服务器将收集所有的相关 actor(也就是其认定在上次更新后发生变化的 actor),然后向客户端发送足够的信息,以便让这些 actor 保持最新状态。

启动服务器

监听服务器

UE4Editor.exe ProjectName MapName?Listen -game

专用服务器

UE4Editor.exe ProjectName MapName -server -game -log

客户端

UE4Editor.exe ProjectName ServerIP -game

连接过程

主要步骤如下:

  1. 客户端发送连接请求。

  2. 如果服务器接受连接,则发送当前地图。

  3. 服务器等待客户端加载此地图。

  4. 加载之后,服务器将在本地调用 AGameMode::PreLogin。

    • 这样可以使 GameMode 有机会拒绝连接

  5. 如果接受连接,服务器将调用 AGameMode::Login

    • 该函数的作用是创建一个 PlayerController,可用于在今后复制到新连接的客户端。成功接收后,这个 PlayerController 将替代客户端的临时 PlayerController (之前被用作连接过程中的占位符)。

    • 此时将调用 APlayerController::BeginPlay。应当注意的是,在此 actor 上调用 RPC 函数尚存在安全风险。您应当等待 AGameMode::PostLogin 被调用完成。

  6. 如果一切顺利,AGameMode::PostLogin 将被调用。

    • 这时,可以放心的让服务器在此 PlayerController 上开始调用 RPC 函数。

---------------------------------------------------------------------------------------------------------------

如何编译构建独立专用服务端

下面步骤假设是以development模式来构建,步骤和shipping模式没差异。

下面步骤中假设我们自己的UE4工程名叫:MyProject

1,下载源码及编译

https://github.com/EpicGames/UnrealEngine/tags

需要现在unrealengine官网上注册并加入github开发组才有权限看到上面的地址。

打开页面后下载一个最新的release版本,解压出来后先运行Setup.bat,会自动下载资源文件,大概有几个G,下载完以后,然后再运行GenerateProjectFiles.bat,会生成VS工程文件,这里假设你已经安装好了VS,我用的vs2015旗舰版,生成完以后打开VS,build类型选择debuggame editor或者development editor,并编译。

2,切换工程的UE4版本

右键点击你的UE4工程文件MyProject.uproject -》 Switch Unreal Engine version,选择刚刚编译出来的UE4,切换版本以后,再右击*.uproject并选择:Generate Visual Studio project files,最后启动VS,启动VS之后再选择一种build类型来编译工程并启动,这里测试用的是development editor类型。

3,cook client content

上面第二步编译并启动运行工程后,这一步来打包客户端(官方文档上叫cook client content),方法和正常客户端版本打包的步骤一样:

Package Project -》 Windows -》 Windows x64。

有人可能会问,安装版本的UE4为什么有没PS4、Xbox等打包选项?是的,只有源码编译的UE4才有这些选项。

这里我们假设打包时选择的输出目录为:D:/PackageTest/,那么输出的客户端exe文件就在D:/PackageTest/WindowsNoEditor/MyProject/Binariesk/Win64/MyProject.exe

这个目录位置会在后面步骤中用到。

如果不cook client content,则后面启动服务端时会报错:

Error: The global shader cache file 'F:/EpicGames/UnrealEngine/Engine/GlobalShaderCache-PCD3D_SM5.bin' is missing.

还有一个纯蓝图UE4工程的构建bug问题:

这个问题v4.7版本时还存在,当前最新版本不知道解决没有。

问题现象是:如果用VS构建之前不添加一个自定义的C++代码,那么构建出来的版本会有问题。

解决办法:在VS构建server版本之前,在UE4 Editor中添加一个C++代码,这个代码随意,只要是C++代码就行(比如添加一个自定义HUD的class),内容默认,不需要编辑。

添加C++方法是:File -》 Add Code to Project。

由于我这里演示的是C++工程,所以不需要添加再添加C++ class。

打包之前记得GameMode和Map是否设置正确了,如果不使用默认的话。


 

 4,添加Server.target.cs配置文件

这一步是关键步骤。

从官网教学项目ShooterGame中拷贝一个文件:\Epic Games\Launcher\VaultCache\ShooterGame_‘版本号’\data\Source\ShooterGameServer.Target.cs

没有安装的话拷贝下面代码新建一个文本文件,并命名为MyProjectServer.Target.cs。位置放在\MyProject\Source\目录下(与其他Target.cs文件同一目录)。

Cpp代码

 收藏代码

  1. // Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.  
  2.   
  3. using UnrealBuildTool;  
  4. using System.Collections.Generic;  
  5.   
  6. public class ShooterGameServerTarget : TargetRules  
  7. {  
  8.     public ShooterGameServerTarget(TargetInfo Target)  
  9.     {  
  10.         Type = TargetType.Server;  
  11.         bUsesSteam = true;  
  12.     }  
  13.   
  14.     //  
  15.     // TargetRules interface.  
  16.     //  
  17.   
  18.     public override bool GetSupportedPlatforms(ref List<UnrealTargetPlatform> OutPlatforms)  
  19.     {  
  20.         // It is valid for only server platforms  
  21.         return UnrealBuildTool.UnrealBuildTool.GetAllServerPlatforms(ref OutPlatforms, false);  
  22.     }  
  23.   
  24.     public override void SetupBinaries(  
  25.         TargetInfo Target,  
  26.         ref List<UEBuildBinaryConfiguration> OutBuildBinaryConfigurations,  
  27.         ref List<string> OutExtraModuleNames  
  28.         )  
  29.     {  
  30.         OutExtraModuleNames.Add("ShooterGame");  
  31.     }  
  32.     public override List<UnrealTargetPlatform> GUBP_GetPlatforms_MonolithicOnly(UnrealTargetPlatform HostPlatform)  
  33.     {  
  34.         List<UnrealTargetPlatform> Platforms = null;  
  35.   
  36.         switch (HostPlatform)  
  37.         {  
  38.             case UnrealTargetPlatform.Linux:  
  39.                 Platforms = new List<UnrealTargetPlatform> { HostPlatform };  
  40.                 break;  
  41.   
  42.             case UnrealTargetPlatform.Win64:  
  43.                 Platforms = new List<UnrealTargetPlatform> { HostPlatform, UnrealTargetPlatform.Linux };  
  44.                 break;  
  45.   
  46.             default:  
  47.                 Platforms = new List<UnrealTargetPlatform>();  
  48.                 break;  
  49.         }  
  50.   
  51.         return Platforms;  
  52.     }  
  53.   
  54.     public override List<UnrealTargetConfiguration> GUBP_GetConfigs_MonolithicOnly(UnrealTargetPlatform HostPlatform, UnrealTargetPlatform Platform)  
  55.     {  
  56.         return new List<UnrealTargetConfiguration> { UnrealTargetConfiguration.Test };  
  57.     }  
  58.     public override List<GUBPFormalBuild> GUBP_GetConfigsForFormalBuilds_MonolithicOnly(UnrealTargetPlatform HostPlatform)  
  59.     {  
  60.         return new List<GUBPFormalBuild>();  
  61.     }  
  62. }  
// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.

using UnrealBuildTool;
using System.Collections.Generic;

public class ShooterGameServerTarget : TargetRules
{
	public ShooterGameServerTarget(TargetInfo Target)
	{
		Type = TargetType.Server;
		bUsesSteam = true;
	}

	//
	// TargetRules interface.
	//

	public override bool GetSupportedPlatforms(ref List<UnrealTargetPlatform> OutPlatforms)
	{
		// It is valid for only server platforms
		return UnrealBuildTool.UnrealBuildTool.GetAllServerPlatforms(ref OutPlatforms, false);
	}

	public override void SetupBinaries(
		TargetInfo Target,
		ref List<UEBuildBinaryConfiguration> OutBuildBinaryConfigurations,
		ref List<string> OutExtraModuleNames
		)
	{
		OutExtraModuleNames.Add("ShooterGame");
	}
    public override List<UnrealTargetPlatform> GUBP_GetPlatforms_MonolithicOnly(UnrealTargetPlatform HostPlatform)
    {
		List<UnrealTargetPlatform> Platforms = null;

		switch (HostPlatform)
		{
			case UnrealTargetPlatform.Linux:
				Platforms = new List<UnrealTargetPlatform> { HostPlatform };
				break;

			case UnrealTargetPlatform.Win64:
				Platforms = new List<UnrealTargetPlatform> { HostPlatform, UnrealTargetPlatform.Linux };
				break;

			default:
				Platforms = new List<UnrealTargetPlatform>();
				break;
		}

		return Platforms;
    }

    public override List<UnrealTargetConfiguration> GUBP_GetConfigs_MonolithicOnly(UnrealTargetPlatform HostPlatform, UnrealTargetPlatform Platform)
    {
        return new List<UnrealTargetConfiguration> { UnrealTargetConfiguration.Test };
    }
	public override List<GUBPFormalBuild> GUBP_GetConfigsForFormalBuilds_MonolithicOnly(UnrealTargetPlatform HostPlatform)
	{
		return new List<GUBPFormalBuild>();
	}
}

 在此基础上需要修改的地方三个地方:

1,类名修改MyProjectServerTarget

2,构造方法修改MyProjectServerTarget

3,OutExtraModuleNames.Add("ShooterGame");修改为OutExtraModuleNames.Add("MyProject");

5,构建Server版本

首先,关掉VS,然后右击工程文件*.uproject-》Generate Visual Studio project files,之所以要重新生成VS工程文件,是因为要确保上一步添加的Target.cs文件能够在编译中生效。

打开VS后,选择build类型Development Server,然后构建。


 

构建之前,检查下Server端的Map和GameMode是否设置了,默认是空的,这样编出的服务端,客户端进来时是一片漆黑。。。(但是客户端确实登陆成功)

 
 

构建完毕以后,输出的server.exe文件位置在:/MyProject/Binaries/Win64/MyProjectServer.exe

然后拷贝这个MyProjectServer.exe文件到上面第3步中提到的目录位置:D:/PackageTest/WindowsNoEditor/MyProject/Binariesk/Win64/目录下。

此时,该目录就会同时存在两个exe文件:MyProject.exe和MyProjectServer.exe。

如果MyProjectServer.exe不和MyProject.exe放在一起,则启动server时会报错(下面只是其众多错误信息中的一条):

default Property warning and errors:

Error: CDO Constructor (WidgetComponent): Failed to find /Engine/EngineMaterials/Widget3DPassThrough_Translucent

6,启动Server

到此为止,已经从构建UE4服务端这个深坑中爬出来了。。。

命令行启动:MyProjectServer.exe -log

执行后会看到弹出一个新的CMD窗口,并看到相关打印信息。

如果不带-log参数,则不会显示命令行窗口,只有一个后台进程。


 
 

7,client连接server

这一步很简单,启动客户端游戏后(双击打包生成的MyProject.exe或者从UE4 Editor中启动游戏均可),按~键,输入:open 127.0.0.1:7777,即可连接上服务端,7777是端口号。如果是shipping模式,是没有这种命令行的,连接服务端需要手动写相关的逻辑代码。

这样UFUNCTION(Server, Reliable, WithValidation)函数就可以与客户端独实现同步了。

注意的是:按~键打开游戏的命令行只对development和debug模式有效,shipping模式无效,另外shipping下也会关闭自带的同步机制(开头提到的)。

其他参考:

Client-Server Model

https://docs.unrealengine.com/latest/INT/Gameplay/Networking/Server/

官方文档v4.4.3:Dedicated Server Guide (Windows & Linux)(必读)

https://wiki.unrealengine.com/Dedicated_Server_Guide_(Windows_%26_Linux)

Networking and Multiplayer

https://docs.unrealengine.com/latest/INT/Gameplay/Networking/index.html

Build Standalone Dedicated Server - Unreal Engine 4.7.2(推荐)

https://www.youtube.com/watch?v=3j72KCPUdog

Unreal Engine 4 - Setting up a dedicated server on Windows x64 platform 

https://www.youtube.com/watch?v=zSA8zUo8oCg

Unreal Engine 4 Dedicated Server Multiplayer Tutorial Unreal Engine Pt1 UE4

https://www.youtube.com/watch?v=BvurHyjI_sY

Unreal Engine 4 Dedicated Server Multiplayer Tutorial Unreal Engine Pt2 UE4

https://www.youtube.com/watch?v=c2Ao4esX4UY

猜你喜欢

转载自blog.csdn.net/qq173681019/article/details/82759524