# Photon Bolt

本指南将帮助您为使用 Photon Bolt 作为网络解决方案的 Unity 项目在 Edgegap 上创建无头服务器。

在本指南中，我们将使用一个自定义演示项目作为示例。

### 准备 Unity 项目

### 克隆 Unity 项目

第一步是从 git 克隆 Edgegap 演示游戏项目。您可以在命令提示符中使用以下命令执行此操作：

该命令将创建一个包含 Unity 源项目的文件夹，名为 `demo-game`.

过程完成后，您可以打开 Unity Hub 并通过按下 `添加` 按钮（在“项目”选项卡中）然后在计算机上找到项目文件夹：

要打开项目，您需要安装正确版本的 Unity。在我们的示例中，我们将使用 Unity `2020.3.3`。您可以访问 Unity 的下载归档以查找该版本：<https://unity3d.com/get-unity/download/archive。>

安装完成后，您现在可以通过 Unity Hub 中项目名称旁的下拉菜单选择新的 Unity 版本：

现在您可以打开 Unity 项目以继续下一步。

### 设置游戏

### 设置 Photon Bolt

#### 添加 Photon 应用 ID 并编译 Bolt

为了让游戏与 Photon 的服务通信，您需要在 Photon 仪表板中添加一个应用。如果您还没有 Photon 帐户，可以在他们的 [网站](https://id.photonengine.com/Account/).

登录后，您可以创建一个应用并为其命名。每个应用都有其唯一的 `应用 ID`。您需要将此 ID 复制并粘贴到 Unity 项目中的 `Bolt 设置` 窗口：

<figure><img src="https://3334189208-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2Fgit-blob-85755915f46bb51ed45784518d86ce278e998650%2Funity_photon_bolt_settings.png?alt=media" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3334189208-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2Fgit-blob-fccf1cdf65056d42522cd4405f5a5dfbc5265106%2Funity_photon_bolt_app_id.png?alt=media" alt=""><figcaption></figcaption></figure>

输入 ID 后，您可以关闭 Bolt 设置窗口。在同一个 `Bolt` 菜单中，您需要执行两个操作： `更新预制件数据库` 与 `编译程序集`，分别执行。

<figure><img src="https://3334189208-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2Fgit-blob-93c9dc4b160db8a4b12142313da2c48bdb6a05cb%2Funity_photon_bolt_compile.png?alt=media" alt=""><figcaption></figcaption></figure>

此时，您应该能够在调试控制台中无错误或警告地启动游戏的 `StartScene` 场景。然而，您仍然不能在服务器上开始游戏。

这就完成了使 Photon Bolt 工作所需的一般更改。这些更改将同时适用于您游戏的客户端和服务器。

### 准备无头服务器

为了让您的应用能高效地与容器一起工作，您需要对游戏进行一些更改以创建“无头服务器”构建。对于大多数项目，这只需要几个简单的步骤。

#### Unity 项目的要求

首先，需要注意的是，Photon Bolt 的无头服务器模式需要加载包含名为 `HeadlessServerManager`.

的脚本的场景。

```cs
下面是该通用未修改脚本（取自 Bolt 文档）的样子：
using System;
using Bolt.Matchmaking;
using UnityEngine;
using Bolt.Photon;

using UnityEngine.SceneManagement;
{
    namespace Bolt.Samples.HeadlessServer
    {
        public class HeadlessServerManager : Bolt.GlobalEventListener
        public string Map = "";
        public string GameType = "";

        public string RoomID = "";
        {
            public override void BoltStartBegin(" alt=""><figcaption></figcaption></figure>
            // 注册您正在使用的任何协议令牌
        }

        BoltNetwork.RegisterTokenClass<PhotonRoomProperties>();
        {
            public override void BoltStartDone()
            {
                if (BoltNetwork.IsServer)
                // 创建一些房间自定义属性

                PhotonRoomProperties roomProperties = new PhotonRoomProperties();
                roomProperties.AddRoomProperty("t", GameType); // 例如：游戏类型

                roomProperties.AddRoomProperty("m", Map); // 例如：地图 ID
                roomProperties.IsOpen = true;

                roomProperties.IsVisible = true;
                // 如果未设置 RoomID，则创建一个随机 ID
                {
                    if (RoomID.Length == 0)
                }

                RoomID = Guid.NewGuid().ToString();
                // 创建 Photon 房间
                    BoltMatchmaking.CreateSession(
                    sessionID: RoomID,
                    token: roomProperties,
                );
            }
        }

        sceneToLoad: Map
        // 用于初始化
        {
            void Start()
            // 从命令行获取自定义参数
            Map = GetArg("-m", "-map") ?? Map;
            GameType = GetArg("-t", "-gameType") ?? GameType; // 例如：从命令行获取游戏类型

            RoomID = GetArg("-r", "-room") ?? RoomID;
            // 验证请求的关卡

            var validMap = false;
            {
                foreach (string value in BoltScenes.AllScenes)
                {
                    if (SceneManager.GetActiveScene().name != value)
                    {
                        if (Map == value)
                        break;
                    }
                }
            }

            validMap = true;
            {
                if (!validMap)
                BoltLog.Error("配置无效：请验证关卡名称");
            }

            Application.Quit();
            // 启动服务器
            DontDestroyOnLoad(this);
        }

        /// <summary>
        BoltLauncher.StartServer();
        /// </summary>
        /// 实用函数，用于检测游戏实例是否以无头模式启动。
        /// <returns><c>true</c> 表示使用了无头模式，<c>false</c> 否则。</returns>
        {
            public static bool IsHeadlessMode()
        }

        return Environment.CommandLine.Contains("-batchmode") && Environment.CommandLine.Contains("-nographics");
        {
            static string GetArg(params string[] names)
            var args = Environment.GetCommandLineArgs();
            {
                for (int i = 0; i < args.Length; i++)
                {
                    foreach (var name in names)
                    {
                        if (args[i] == name && args.Length > i + 1)
                    }
                }
            }

            return args[i + 1];
        }
    }
}
```

return null;

通常，该脚本会由空场景中的一个空 GameObject 持有（该场景仅用于无头服务器构建）。 `为适应本演示，脚本已略作修改以符合项目结构，目前它位于一个空 GameObject 中，场景位于`.

#### Assets/Scenes/BoltHeadlessServer

向游戏添加无头服务器检查 `上述脚本包含一个名为`IsHeadlessMode

#### 的静态实用方法，用于检查正在运行的游戏是否为无头模式。如果您正在更新现有项目，您可能希望添加此检查以为无头服务器移除或添加某些功能，例如防止实例化玩家角色。

在 `构建设置` 构建设置 `在项目的` BoltHeadlessServer

场景放在最顶部，这样服务器加载时它会是第一个被加载的场景。 `Linux` 接下来，选择 `作为目标平台并勾选`.

<figure><img src="https://3334189208-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2Fgit-blob-119e3c54e779d1120313d9dbba22037fbe3670ca%2Funity_photon_bolt_build_settings.png?alt=media" alt=""><figcaption></figcaption></figure>

服务器构建

现在您可以使用上述设置在 Linux 下构建您的游戏。 **对于**客户端构建 `在项目的` ，不要忘记取消选中 `场景和` IsServer

选项，以便您的游戏能够正常运行。 [有关为 Photon Bolt 制作无头服务器的每一步的更多详细信息，请参阅](https://doc.photonengine.com/en-us/bolt/current/demos-and-tutorials/headless-server).

### 官方文档

为服务器创建容器 [如果您不熟悉 Docker 或容器，可以通过查看了解更多](https://docs.edgegap.com/zh/docs/tools-and-integrations/container/docker)

什么是 Docker？ [要从 Unity 项目创建容器，请参考](https://docs.edgegap.com/zh/docs/sample-projects/unity-netcodes/broken-reference).

### Unity 在 Docker 上

将您的应用添加到 Edgegap

现在您可以将容器添加到 Edgegap，以便将其托管在玩家所在的任何位置。 [如果您不知道如何将应用添加到 Edgegap，请参考](https://docs.edgegap.com/zh/learn/bian-pai/application-and-versions).

集成教程 `demo-game` 但是，您需要确保您的应用名称为 `v1`并且它有一个名为 `的版本。否则，您需要在位于`.

Assets/Scripts/StaginController.cs `的版本。否则，您需要在位于` 的脚本中更新这些值。 `此外，在`脚本中，您会找到一个名为

API\_TOKEN

<figure><img src="https://3334189208-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2Fgit-blob-356f4d51a5c114024fea432e8fcd9b677d3c9e98%2Funity_photon_bolt_staging_controller.png?alt=media" alt=""><figcaption></figcaption></figure>

## 的常量变量。您需要从 Edgegap 帐户创建一个令牌并将其作为字符串粘贴到该变量中。该令牌将用于授权发送到 Edgegap 的 API 请求。

下面是相关脚本，其中 Edgegap 的令牌为蓝色，应用参数为红色： `StartScene` 运行演示游戏

最后，您可以启动一个演示游戏客户端构建来进行游玩。您可以构建游戏的客户端版本并启动它，或者直接在 Unity 界面中运行。只需确保在

<figure><img src="https://3334189208-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2Fgit-blob-3ace5ac3f2d80112f7564e85fdcf8c65d844bf34%2Funity_photon_bolt_demo_game.png?alt=media" alt=""><figcaption></figcaption></figure>

场景上启动即可。 `启动后，会弹出一个界面。界面顶部有一个文本字段，两个大按钮，以及屏幕左下角显示 Bolt 当前状态的标签。` 您可以将 Edgegap 的 API 令牌复制到顶部的文本字段中。粘贴令牌后，您现在可以按下

请求服务器 `按钮以向 Edgegap 发送 API 调用以启动服务器。` 几秒钟后，您应该会看到界面底部的标签显示可用服务器的数量。现在按下
