# 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="/files/dd21c06abda724cdb0f62054502acf1fbb23060e" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/96328ff25999d9067fa3ac475f1c25d6b9c78bda" alt=""><figcaption></figcaption></figure>

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

<figure><img src="/files/53663da3e7db3c72203711418ea236ce7c29ed80" 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="/files/05f405c248bd3ea6b7857226fd072ea95657dba1" alt=""><figcaption></figcaption></figure>

服务器构建

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

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

### 官方文档

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

什么是 Docker？ [要从 Unity 项目创建容器，请参考](broken://pages/0c42ece8adc18305e213a10ec872fe29dae5e3e9).

### Unity 在 Docker 上

将您的应用添加到 Edgegap

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

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

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

API\_TOKEN

<figure><img src="/files/3dbf63c302c031357ec29c218a0f1149cbe8c01f" alt=""><figcaption></figcaption></figure>

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

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

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

<figure><img src="/files/7c3dca0098ab03c502dbb7e44ba2626f6bf29dbf" alt=""><figcaption></figcaption></figure>

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

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


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.edgegap.com/zh/docs/sample-projects/unity-netcodes/photon-bolt-on-arbitrium.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
