> ## Documentation Index
> Fetch the complete documentation index at: https://devdocs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# GSDK 项目设置

> 在 Unreal Engine ThirdPersonMP 项目中添加并配置 PlayFab GSDK 插件,以便专用服务器构建可以托管在 PlayFab Multiplayer Servers 上。

# 将 GSDK 添加到项目

本文介绍如何升级现有项目,使其可以托管在 PlayFab Multiplayer Servers (MPS) 上。该过程包括将 PlayFab GSDK 添加并配置到 Unreal 项目中。此处的说明是使用 Unreal ThirdPersonMP 模板项目编写的。

请注意,您的 Unreal 项目必须具有以下功能:

* 网络
* 多人游戏
* 专用游戏服务器

如果没有,您需要返回到[示例项目设置](/services/playfab/multiplayer/servers/server-sdks/unreal-gsdk/third-person-mp-example-project-setup)指南,将您的项目配置为启用网络的多人游戏,并具备专用服务器功能。

## 目标

我们将向您的项目添加并配置 PlayFab Unreal GSDK,并在本地测试以验证它有望在 PlayFab Multiplayer Services 上正常工作。

## 要求

* 下载 Visual Studio。[社区版](https://visualstudio.microsoft.com/vs/community/)是免费的。
  * 所需的工作负载:.NET 桌面开发和使用 C++ 的桌面开发
* 下载 Unreal Engine 源代码。有关说明,请参见[下载 Unreal Engine 源代码(外部)](https://docs.unrealengine.com/ProgrammingAndScripting/ProgrammingWithCPP/DownloadingSourceCode/)。
* 已完成的 [ThirdPersonMP 示例项目](/services/playfab/multiplayer/servers/server-sdks/unreal-gsdk/third-person-mp-example-project-setup),或具有类似功能的项目
* [PlayFab Unreal GSDK 插件](https://github.com/PlayFab/gsdk/tree/master/UnrealPlugin)
* \[可选] [PlayFab Marketplace 插件](https://www.unrealengine.com/marketplace/product/playfab-sdk)或 [GitHub 上的源代码版本](https://github.com/PlayFab/UnrealMarketplacePlugin)。此插件对于 GSDK 不是必需的,但对于许多 PlayFab 服务(包括登录)是必需的。

## C++ 实现

### 将插件添加到项目

按照以下步骤将 Unreal GSDK 添加到您的项目:

* 转到您的 Unreal 项目
* 打开文件资源管理器,在游戏的根目录中创建一个 **Plugins** 文件夹。在 Plugins 文件夹中,创建一个名为 **PlayFabGSDK** 的文件夹。
* 转到 **\{depot}\GSDK\gsdk\UnrealPlugin**。将 **UnrealPlugin** 文件夹中的所有文件拖到 **Plugins/PlayFabGSDK** 文件夹中。
* 最后,使用您选择的文本编辑器打开 `{ProjectName}.uproject` 文件。在 plugins 数组中,添加 "PlayFabGSDK" 插件。

请参见下面的示例:

```json theme={null}
{
    "FileVersion": 3,
    "EngineAssociation": "{YourEngineVersion}",
    "Category": "",
    "Description": "",
    "Modules": [
        {
            "Name": "{ProjectName}",
            "Type": "Runtime",
            "LoadingPhase": "Default",
            "AdditionalDependencies": [
                "Engine"
            ]
        }
    ],
    "Plugins": [                    // Add this if it doesn't exist
        {                           // Add this
            "Name": "PlayFabGSDK",  // Add this
            "Enabled": true         // Add this
        }                           // Add this
    ]                               // Add this if it doesn't exist
}
```

### 将插件包含在您的模块中

* 更新 \{ProjectName}.Build.cs 文件,将 "PlayFabGSDK" 添加到 PublicDependencyModuleNames.AddRange(); 列表中,如下所示:

```csharp theme={null}
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "HeadMountedDisplay", "PlayFabGSDK" });
```

* 右键单击 `{ProjectName}.uproject` 文件并选择 **Switch Unreal Engine version** 选项,这样您就可以快速检查当前使用的 Unreal Engine 版本。应该会出现下面看到的弹出窗口。如果您已经看到 Unreal Engine 版本是源代码构建,则无需更改任何内容,请单击 Cancel。如果 Unreal 版本当前不是源代码构建,请从下拉列表中选择它,然后单击 OK。

<img src="https://mintcdn.com/microsoft-4404708b/U1LR64ZWxo45eXwl/images/playfab/multiplayer/servers/server-sdks/unreal-gsdk/SelectUnrealEngineVersion.png?fit=max&auto=format&n=U1LR64ZWxo45eXwl&q=85&s=bd8e143a756f3896fe41188b23adcb34" alt="显示 &#x22;Select Unreal Engine Version&#x22; 窗口的图像" width="253" height="137" data-path="images/playfab/multiplayer/servers/server-sdks/unreal-gsdk/SelectUnrealEngineVersion.png" />

* 再次右键单击 `{ProjectName}.uproject` 文件并选择 "Generate Visual Studio Project Files"。

* 最后,通过选择 Development Editor 配置在 Visual Studio 中构建项目并启动编辑器。

<img src="https://mintcdn.com/microsoft-4404708b/U1LR64ZWxo45eXwl/images/playfab/multiplayer/servers/server-sdks/unreal-gsdk/DevelopmentEditor.png?fit=max&auto=format&n=U1LR64ZWxo45eXwl&q=85&s=e039b6ef96b11027a01432cdbd6af933" alt="描绘 Visual Studio 中以 Development Editor Mode 构建选项的图像" width="519" height="287" data-path="images/playfab/multiplayer/servers/server-sdks/unreal-gsdk/DevelopmentEditor.png" />

### 项目设置

一旦您的项目启用了服务器模式,您将拥有一个 \{ProjectName}Server.Target.cs 文件。

结果应该类似于:

```csharp theme={null}
public class {ProjectName}ServerTarget : TargetRules
{
    public {ProjectName}ServerTarget( TargetInfo Target) : base(Target)
    {
        Type = TargetType.Server;
        DefaultBuildSettings = BuildSettingsVersion.V2;
        ExtraModuleNames.AddRange( new string[] { "{ProjectName}" } );

    // You may have additional configuration based on your server needs
    }
}
```

对于 Windows 构建,您可能需要添加以下可选配置:

```csharp theme={null}
DisablePlugins.Add("WMFMediaPlayer");
DisablePlugins.Add("AsyncLoadingScreen"); //if you are using this plugin
DisablePlugins.Add("WindowsMoviePlayer");
DisablePlugins.Add("MediaFoundationMediaPlayer");
```

注意:这些配置对于 Linux 服务器构建是无效的。

### 创建/更新 GameInstance 类

#### 创建 GameInstance 类

如果您正在从头开始创建项目,并且尚未拥有 GameInstance 类,请首先按照以下示例说明创建 GameInstance 类。如果您使用的是已经具有 GameInstance 类的项目(例如 Unreal 示例库中的 ShooterGame),请转到标题为 ***修改 GameInstance 类*** 的部分。

***

在 Unreal Editor 中:

* 选择 **Files**
* 选择 **Create a new C++ class**
* 选择 **Show all classes**
* 在搜索字段中键入 `GameInstance`
  * 按照所述直接选择它,所有内容应该都能正确生成,然后您可以添加我们下面详述的函数
* 关闭 Unreal 并再次在源代码构建模式下 **生成项目文件**
* 使用 Visual Studio,打开这些新创建的文件并按照说明修改 GameInstance 类。

#### 修改 GameInstance 类

根据您项目的设置,您可以使用 C++ 或蓝图修改 GameInstance 类。下面介绍了两种方法,您应该选择适合您需求的那一种。

#### C++ 实现

找到您的 GameInstance 类,它很可能被命名为类似 \{ProjectName}GameInstance 或 MyGameInstance。从现在开始,您的 GameInstance 类将用 \[YourGameInstanceClassName] 表示。

##### 修改 GameInstance 头文件

首先,检查 include 语句并确保您的 GameInstance 类 (\[YourGameInstanceClassName].h) 的头文件中包含以下内容:

```cpp theme={null}
#include "CoreMinimal.h"
#include "Engine/GameInstance.h"
#include "MyGameInstance.generated.h"
```

\[可选] 使用以下代码,用户可以专门为 GameInstance 引入日志通道。或者,使用 LogTemp 进行日志记录就足够了。

```cpp theme={null}
DECLARE_LOG_CATEGORY_EXTERN(LogPlayFabGSDKGameInstance, Log, All);
```

然后,将以下声明添加到 public 部分:(如果您已经有 Init() 函数,则无需再次包含另一个声明)

```cpp theme={null}
public:

    virtual void Init() override;
    virtual void OnStart() override;
```

然后,将以下方法声明添加到 protected 部分:

```cpp theme={null}
protected:

    UFUNCTION()
    void OnGSDKShutdown();

    UFUNCTION()
    bool OnGSDKHealthCheck();

    UFUNCTION()
    void OnGSDKServerActive();

    UFUNCTION()
    void OnGSDKReadyForPlayers();

};
```

##### 修改 GameInstance CPP 文件

然后,找到 \[YourGameInstanceClassName].cpp 文件。

请确保包含以下内容:

```cpp theme={null}
#include "[YourGameInstanceClassName].h"
#include "PlayfabGSDK.h"
#include "GSDKUtils.h"
```

如果已在头文件中引入自定义日志通道,则需要以下代码:

```cpp theme={null}
DEFINE_LOG_CATEGORY(LogPlayFabGSDKGameInstance);

```

然后找到您的 Init() 函数。如果您还\_**没有**\_ Init() 函数,则添加该函数,如下所示:

###### 创建 Init() 函数

```cpp theme={null}
void U[YourGameInstanceClassName]::Init()
{
    FOnGSDKShutdown_Dyn OnGSDKShutdown;
    OnGSDKShutdown.BindDynamic(this, &UMyGameInstance::OnGSDKShutdown);
    FOnGSDKHealthCheck_Dyn OnGSDKHealthCheck;
    OnGSDKHealthCheck.BindDynamic(this, &UMyGameInstance::OnGSDKHealthCheck);
    FOnGSDKServerActive_Dyn OnGSDKServerActive;
    OnGSDKServerActive.BindDynamic(this, &UThirdPersonGameInstance::OnGSDKServerActive);
    FOnGSDKReadyForPlayers_Dyn OnGSDKReadyForPlayers;
    OnGSDKReadyForPlayers.BindDynamic(this, &UThirdPersonGameInstance::OnGSDKReadyForPlayers);

    UGSDKUtils::RegisterGSDKShutdownDelegate(OnGSDKShutdown);
    UGSDKUtils::RegisterGSDKHealthCheckDelegate(OnGSDKHealthCheck);
    UGSDKUtils::RegisterGSDKServerActiveDelegate(OnGSDKServerActive);
    UGSDKUtils::RegisterGSDKReadyForPlayersDelegate(OnGSDKReadyForPlayers);
}
```

***

如果您**已经有** Init() 函数,请检查 `[YourGameInstanceClassName].cpp` 文件,查看是否有指示实例是否为专用服务器的变量。**如果您能找到此变量**,请在 Init() 函数的末尾添加以下内容:

###### 修改现有的 Init() 函数

```cpp theme={null}
    if (IsDedicatedServerInstance() == true)
    {
        FOnGSDKShutdown_Dyn OnGsdkShutdown;
        OnGsdkShutdown.BindDynamic(this, &UShooterGameInstance::OnGSDKShutdown);
        FOnGSDKHealthCheck_Dyn OnGsdkHealthCheck;
        OnGsdkHealthCheck.BindDynamic(this, &UShooterGameInstance::OnGSDKHealthCheck);
        FOnGSDKServerActive_Dyn OnGSDKServerActive;
        OnGSDKServerActive.BindDynamic(this, &UShooterGameInstance::OnGSDKServerActive);
        FOnGSDKReadyForPlayers_Dyn OnGSDKReadyForPlayers;
        OnGSDKReadyForPlayers.BindDynamic(this, &UShooterGameInstance::OnGSDKReadyForPlayers);

        UGSDKUtils::RegisterGSDKShutdownDelegate(OnGsdkShutdown);
        UGSDKUtils::RegisterGSDKHealthCheckDelegate(OnGsdkHealthCheck);
        UGSDKUtils::RegisterGSDKServerActiveDelegate(OnGSDKServerActive);
        UGSDKUtils::RegisterGSDKReadyForPlayers(OnGSDKReadyForPlayers);
    }
```

**通过调用以下用于为 MPS 设置默认端口的函数来完成 Init() 函数**。

```cpp theme={null}
#if UE_SERVER
    UGSDKUtils::SetDefaultServerHostPort();
#endif
```

***

最后,将这些方法实现添加到 `[YourGameInstanceClassName].cpp` 文件的底部:

```cpp theme={null}
void UMyGameInstance::OnStart()
{
    UE_LOG(LogPlayFabGSDKGameInstance, Warning, TEXT("Reached onStart!"));
    UGSDKUtils::ReadyForPlayers();
}

void UMyGameInstance::OnGSDKShutdown()
{
    UE_LOG(LogPlayFabGSDKGameInstance, Warning, TEXT("Shutdown!"));
    FPlatformMisc::RequestExit(false);
}

bool UMyGameInstance::OnGSDKHealthCheck()
{
    // Uncomment the next line if you want your server to log something at every heartbeat for sanity check.
    /* UE_LOG(LogPlayFabGSDKGameInstance, Warning, TEXT("Healthy!")); */
    return true;
}

void UThirdPersonGameInstance::OnGSDKServerActive()
{
    /**
     * Server is transitioning to an active state.
     * Optional: Add in the implementation any code that is needed for the game server when
     * this transition occurs.
     */
    UE_LOG(LogPlayFabGSDKGameInstance, Warning, TEXT("Active!"));
}

void UThirdPersonGameInstance::OnGSDKReadyForPlayers()
{
    /**
     * Server is transitioning to a StandBy state. Game initialization is complete and the game
     * is ready to accept players.
     * Optional: Add in the implementation any code that is needed for the game server before
     * initialization completes.
     */
    UE_LOG(LogPlayFabGSDKGameInstance, Warning, TEXT("Finished Initialization - Moving to StandBy!"));
}
```

#### 蓝图实现

只有当您决定继续使用蓝图实现而不是纯 C++ 实现时,才需要这部分。

* 观察 Unreal Editor 中的 Content Browser 窗口
* 选择或创建一个文件夹来包含新的蓝图
* 右键单击并创建一个蓝图类
* 在 All classes 下拉菜单中,找到您的 GameInstance 类
  * 在此示例中,蓝图被命名为 "MyGameInstance"
* 双击蓝图
* 在左侧,将鼠标悬停在函数字段上,并选择 Override 下拉菜单
* 选择 Init 函数
* 在图表中右键单击并添加所有的注册 GSDK 函数
* 对于 GSDK Shutdown 和 Maintenance Delegate,从红色方块中拖出一条线,然后选择 "Add Custom Event"
* 对于 "Register GSDK Health Check Delegate",在 "Event Dispatchers" 中选择 "Create Event"。
* <img src="https://mintcdn.com/microsoft-4404708b/U1LR64ZWxo45eXwl/images/playfab/multiplayer/servers/server-sdks/unreal-gsdk/BlueprintAddRegisterHealthCheckDelegate.png?fit=max&auto=format&n=U1LR64ZWxo45eXwl&q=85&s=034809788a483673c44c06da1b4a5ca4" alt="添加 PlayFab GSDK Health Check" width="1909" height="1059" data-path="images/playfab/multiplayer/servers/server-sdks/unreal-gsdk/BlueprintAddRegisterHealthCheckDelegate.png" />
* 在新节点的下拉菜单中选择 "Create matching function"。**这一点很重要,因为 GSDK Health Check Delegate 有一个返回值。**
* <img src="https://mintcdn.com/microsoft-4404708b/U1LR64ZWxo45eXwl/images/playfab/multiplayer/servers/server-sdks/unreal-gsdk/BlueprintRegisterHealthCheckDelegate.png?fit=max&auto=format&n=U1LR64ZWxo45eXwl&q=85&s=2fb2c95b58172f1e6ad1f1483295c7f7" alt="注册 PlayFab GSDK Health Check" width="1909" height="844" data-path="images/playfab/multiplayer/servers/server-sdks/unreal-gsdk/BlueprintRegisterHealthCheckDelegate.png" />
* 在该函数中,请确保勾选返回布尔值。
* <img src="https://mintcdn.com/microsoft-4404708b/U1LR64ZWxo45eXwl/images/playfab/multiplayer/servers/server-sdks/unreal-gsdk/BlueprintGSDKHealthCheckFunction.png?fit=max&auto=format&n=U1LR64ZWxo45eXwl&q=85&s=529d14dc173c83d6a75c5cd2cb508483" alt="PlayFab GSDK Health Check 函数" width="1087" height="373" data-path="images/playfab/multiplayer/servers/server-sdks/unreal-gsdk/BlueprintGSDKHealthCheckFunction.png" />
* 不要忘记将所有节点连接到 Event Init 节点。
* 最后添加 "ReadyforPlayers" 节点,以便能够对 PlayFab 的 ready 信号做出反应。
* 此外,不要忘记添加 "SetDefaultServerHostPort" 节点以连接到 GSDK 期望的端口。
* 对于您想要在蓝图中添加的每个 GSDK 函数/节点,您可以通过在新节点中键入函数名称的前几个字母,并查看预期的 GSDK 函数出现在建议中来验证它是否存在。
* 最后,您的蓝图应该类似于下图所示。
* <img src="https://mintcdn.com/microsoft-4404708b/U1LR64ZWxo45eXwl/images/playfab/multiplayer/servers/server-sdks/unreal-gsdk/BlueprintFullGraph.png?fit=max&auto=format&n=U1LR64ZWxo45eXwl&q=85&s=b4c7da43fbe2085a2fa9d1f2a7daeddb" alt="PlayFab GSDK 完整图表" width="2387" height="899" data-path="images/playfab/multiplayer/servers/server-sdks/unreal-gsdk/BlueprintFullGraph.png" />

## 设置 GameInstance 类

创建了与 gsdk 集成的自定义 GameInstance 类后,您必须配置项目以实际使用这个新创建的 GameInstance 类。有两种方法可以做到这一点 - 通过 Unreal Engine 编辑器或直接编辑 DefaultEngine.ini。

### 在 Unreal Editor 中

在编辑器中,可以通过编辑器中的 UI 设置默认 GameInstance。在编辑器中,转到 **Edit** -> **Project Settings**。从打开的窗口中,导航到左侧的 **Maps\&Modes**。滚动到底部,然后您可以直接将 `GameInstanceClass` 选项设置为您新的 GameInstance 类(避免拼写错误,必须完全匹配)。

### 在 DefaultEngine.ini 中

或者您可以更新 DefaultEngine.ini 文件并添加以下行:

```ini theme={null}
[/Script/EngineSettings.GameMapsSettings]
GameInstanceClass=/Script/{ProjectName}.MyGameInstance
```

## 包括 Windows 专用服务器的先决条件

有两种方法可以包括应用程序本地的先决条件 - 通过 Unreal Engine 编辑器或编辑 DefaultGame.ini。

### 在 Unreal Editor 中

在编辑器中,转到 Edit -> Project Settings。在打开的窗口中,导航到左侧的 Packaging。滚动到列表底部,然后勾选 "Include app-local prerequisites"。

### 在 DefaultGame.ini 中

或者您可以使用以下代码更新 DefaultGame.ini:

```ini theme={null}
[/Script/UnrealEd.ProjectPackagingSettings]
IncludeAppLocalPrerequisites=True
```

如果该类别已经存在于您的 DefaultGame.ini 中,那么只需将第二行添加到其中即可。此配置可确保所有应用程序本地依赖项也随项目一起发布。

如果您正在使用持续集成 (CI),您可以将其添加到您的设置中,以便仅在构建专用服务器时打开此标志,这样只有在专用服务器构建时才会添加先决条件的 dll。

## 后续步骤

您现在已经准备好在本地计算机上[构建您的项目](/services/playfab/multiplayer/servers/server-sdks/unreal-gsdk/building-the-third-person-mp-example-project)。

或者,您可以返回到主要的 [Unreal GSDK 插件](/services/playfab/multiplayer/servers/server-sdks/unreal-gsdk#unreal-project-build-configurations)指南。


## Related topics

- [GSDK 示例项目创建](/zh-CN/services/playfab/multiplayer/servers/server-sdks/unreal-gsdk/third-person-mp-example-project-setup.md)
- [Win32 快速入门](/zh-CN/services/playfab/sdks/c/quickstart-win32.md)
- [Defold 的 Lua 快速入门](/zh-CN/services/playfab/sdks/lua/quickstart-defold.md)
- [PlayFab 统一 SDK 快速入门设置](/zh-CN/services/playfab/sdks/unified-sdk/quickstart-setup.md)
- [GDK 快速入门](/zh-CN/services/playfab/sdks/c/quickstart-gdk.md)
