> For the complete documentation index, see [llms.txt](https://docs.edgegap.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.edgegap.com/zh/unity.md).

# Unity - 入门指南

通过实践学习，并在 Edgegap 上部署你的第一个专用服务器。在本指南结束时，你将能够零成本使用 Edgegap 部署一个专用服务器。

{% embed url="<https://youtu.be/4FR04V4YEUk>" %}

## ✔️ 准备工作

开始之前，请务必 [在 Edgegap 创建一个免费账户](https://app.edgegap.com/auth/register) （无需信用卡）。你可以 [之后邀请你的团队成员](https://app.edgegap.com/user-settings?tab=organizations)，即使他们还没有 Edgegap 账户。

**在你的开发机器上配置一些基本内容：**

<details>

<summary>安装 Unity Linux 构建支持模块</summary>

* 使用 Unity Hub 选择 选项卡 **安装**，访问 **设置** 和 **添加模块** 对于您打算与 Edgegap 平台一起使用的每个 Unity 版本：

<figure><img src="https://3334189208-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2FylRG4r8orenZrw5ijjpJ%2Fimage.png?alt=media&amp;token=fb981825-8a15-4c07-9180-0f79a6a77a91" alt=""><figcaption></figcaption></figure>

* 向下滚动以选择并安装以下 Unity 模块：
  * **Linux 构建支持（IL2CPP），**
    * **Linux 构建支持（Mono），**
    * **Linux 专用服务器构建支持**

<figure><img src="https://3334189208-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2FuXtyqoLhBOk8CZJ4WdzA%2Fimage.png?alt=media&amp;token=19e956ed-a731-420d-b911-130c334794fc" alt=""><figcaption></figcaption></figure>

</details>

<details>

<summary><a href="https://www.docker.com/products/docker-desktop/">安装 Docker Desktop（或 Docker CLI）</a></summary>

* [从官方来源安装 Docker Desktop](https://www.docker.com/products/docker-desktop/) （无需账户）。
* 完成安装后重启计算机。

</details>

<details>

<summary><a href="https://github.com/edgegap/edgegap-unity-plugin">安装 Edgegap 的 Unity Dedicated Servers Quickstart 插件</a></summary>

请参阅 [官方插件仓库](https://github.com/edgegap/edgegap-unity-plugin) 有关安装的详细说明。

该插件已通过测试，支持 Unity 2021.2+ 版本，包括所有 LTS 版本、Unity 2023 和 Unity 6。

{% embed url="<https://youtu.be/3a5veDyxpoE>" %}

</details>

{% hint style="info" %}
**对你的服务器构建有信心吗？** 跳转到 [#customize-server-image](#customize-server-image "mention") 或 [高级功能](/zh/learn/advanced-features.md) 了解更多。
{% endhint %}

## ⚙️ 1. 连接账号

☑️ 登录并确认你的 Unity 控制台中没有与 Edgegap 插件相关的新错误。

✅ 现在你可以进入下一步了。

<details>

<summary>故障排查与常见问题</summary>

`!Success: 400 错误请求 - POST | https://api.edgegap.com/v1/wizard/init-quick-start - {"message": "浏览器（或代理）发送了一个此服务器无法理解的请求。"}`

* 如果你是通过复制 ZIP 文件安装的，或者使用了一个通过这种方式安装了插件的示例项目，那么你需要手动安装包依赖项，包括 Newtonsoft JSON 库，参见 [官方插件仓库](https://github.com/edgegap/edgegap-unity-plugin/tree/main?tab=readme-ov-file#instructions-1).
* 如果不是这种情况，请通过 [社区 Discord](https://discord.gg/NgCnkHbsGp) 联系我们寻求帮助。

</details>

## 🔧 2. 构建游戏服务器

无论你使用的是 Windows、Mac 还是 Linux 机器，你都将 **需要为 Linux 运行时构建你的服务器**，因为如今大多数云服务提供商（包括 Edgegap）都运行在 Linux 上。别担心，使用我们的插件完成这一点不需要任何 Linux 知识。

☑️ **确认你已安装所需的 Unity Linux 构建工具。**

<details>

<summary>安装 Unity Linux 构建支持模块</summary>

* 使用 Unity Hub 选择 选项卡 **安装**，访问 **设置** 和 **添加模块** 对于您打算与 Edgegap 平台一起使用的每个 Unity 版本：

<figure><img src="https://3334189208-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2FylRG4r8orenZrw5ijjpJ%2Fimage.png?alt=media&amp;token=fb981825-8a15-4c07-9180-0f79a6a77a91" alt=""><figcaption></figcaption></figure>

* 向下滚动以选择并安装以下 Unity 模块：
  * **Linux 构建支持（IL2CPP），**
    * **Linux 构建支持（Mono），**
    * **Linux 专用服务器构建支持**

<figure><img src="https://3334189208-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2FuXtyqoLhBOk8CZJ4WdzA%2Fimage.png?alt=media&amp;token=19e956ed-a731-420d-b911-130c334794fc" alt=""><figcaption></figcaption></figure>

</details>

☑️ 编辑构建设置以 **确保所有必需的游戏场景都已包含**.

{% hint style="info" %}
**高级 Unity 用户** - 可选地更改 [Unity 构建设置](https://docs.unity3d.com/Manual/BuildSettings.html). 注意！这可能会破坏你的构建。
{% endhint %}

☑️ 可选：从 Edgegap Server Hosting 菜单（右键单击 /）为你的初始服务器场景添加用于端口验证和环境引导的特定 netcode 脚本 :heavy\_plus\_sign: 在你的 Hierarchy 窗口中）。

<figure><img src="https://3334189208-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2FZ8dV9ERoV3rczrXXUdV9%2Fimage.png?alt=media&amp;token=f7c44a27-7521-4392-9d11-276c48410ed0" alt="" width="360"><figcaption></figcaption></figure>

{% hint style="info" %}
完成第 [#id-6.-deploy-to-cloud](#id-6.-deploy-to-cloud "mention")步后，如果你的 netcode 地址或端口与 Edgegap 的 [应用版本端口映射](/zh/learn/bian-pai/application-and-versions.md#other-parameters-optional) 配置不匹配，端口验证脚本会记录警告。
{% endhint %}

{% hint style="success" %}
服务器构建应在你的 netcode 传输中使用地址 `0.0.0.0`  和端口 `7777`  。如果你自定义了端口，请在你的 [应用与版本](/zh/learn/bian-pai/application-and-versions.md#port-mapping) 中指定相同的设置，一旦你 [#id-5.-upload-to-edgegap](#id-5.-upload-to-edgegap "mention").
{% endhint %}

☑️ 一旦你对配置满意，就点击 **构建服务器**，等待进程完成，并确认你的 Unity 控制台中没有新错误。完成此步骤后，你的项目根目录中将出现一个 **新文件夹** - `Builds/EdgegapServer/ServerBuild` .

✅ 现在你可以进入下一步了。

<details>

<summary>故障排查与常见问题</summary>

Unity：唯一支持的独立目标是 Windows x64 和带 OpenXR 的 OSX。

* 在构建服务器之前，打开你的 Packages 并禁用 OpenXR。
* OpenXR 插件仅客户端需要，与 Linux 服务器构建不兼容。将其从服务器构建中排除不会丢失任何功能。

</details>

## 🐋 3. 容器化服务器

在一个开发者团队中工作意味着要共享代码。当出现问题时，您最不想听到的就是“在我的机器上可以运行”。游戏服务器必须能够在任何机器上可靠运行，因为成功的游戏服务器会在世界各地成千上万台服务器机器上运行。

为了帮助使您的服务器可靠，我们使用 Docker —— 一种虚拟化软件，确保您的所有服务器代码依赖项直到操作系统级别始终完全相同，无论服务器如何或在哪里启动。

{% hint style="info" %}
我们建议观看 [“永远不要本地安装”（视频）](https://www.youtube.com/watch?v=J0NuOlA2xDc\&ab_channel=Coderized). **使用 Docker 不需要使用 Dockerhub**。Docker ≠ Dockerhub。把 Docker 想象成一个编程引擎，把 Dockerhub 想成它的应用商店。
{% endhint %}

☑️ 首先点击 **验证** 按钮，确保你已完成 [#preparation](#preparation "mention").

<details>

<summary><a href="https://www.docker.com/products/docker-desktop/">安装 Docker Desktop（或 Docker CLI）</a></summary>

* [从官方来源安装 Docker Desktop](https://www.docker.com/products/docker-desktop/) （无需账户）。
* 完成安装后重启计算机。

</details>

☑️ 你可以配置以下选项（或保留默认值）：

* **构建路径** 是你的服务器构建产物的相对路径，现在先保留默认值。

{% hint style="warning" %}
**将构建保留在项目文件夹内**，Docker 只接受相对于项目根目录的构建路径。
{% endhint %}

* **镜像名称** 是你自行选择的唯一标识，用于在发布前标记你的服务器构建。
  * 通常，这会包含你的游戏名称，例如“my-game-server”。
* **镜像标签** 是指向镜像特定版本的标识符。
  * 术语“构建产物”有时用于指代镜像的特定版本。
  * 时间戳是标记的一个很好的默认选项，例如 `2024.01.30-16.23.00-UTC` .
* **Dockerfile 路径** 可用于自定义镜像的配方。
  * 我们建议现在先保留默认设置，你可以稍后在第 [#customize-image](#customize-image "mention").
* **可选的 docker 构建参数** 中了解更多，它们可用于进一步指导 Docker 处理更细微的细节。
  * 我们建议现在先保留默认设置，你可以 [稍后在 Docker 文档中阅读更多内容](https://docs.docker.com/reference/cli/docker/image/build/#options).

☑️ 一旦你对配置满意，就点击 **使用 Docker 容器化**，等待进程完成，并确认你的 Unity 控制台中没有新错误。完成此步骤后，你的项目根目录中将出现一个 **你的本地机器上会出现一个新的镜像**。你可以在 Docker Desktop 的 Images 标签页（Local 下，默认）中验证这一点，或者在 docker CLI 中运行 `docker images` .

{% hint style="info" %}
**从源代码重建** 将自动构建并容器化，以 **加快你下一次构建**.
{% endhint %}

✅ 现在你可以进入下一步了。

<details>

<summary>故障排查与常见问题</summary>

`/bin/bash: docker: command not found` ，或者 `could not find Packages\com.edgegap.unity-servers-plugin\Editor`

* 首先，确保你已完成 [开发者工具](/zh/unity/developer-tools.md#usage-requirements).
* 确认你已验证你的 Edgegap 账号，你应该已经通过电子邮件收到验证链接。
* 在更新 Docker Desktop 后，某些设置可能已重置。尝试进入 Docker Desktop 设置 / 高级，并在“Choose how to configure the installation of Docker’s CLI tools:”中选择“System (requires password)”。

***

`docker build 需要恰好 1 个参数`

* 请确认你的镜像标签不包含任何空白字符（空格、制表符）。重新输入镜像标签值可确保你没有意外复制到这些字符。

***

`（HTTP 代码 400）异常 - 无效的标签格式`

* 这是一个 [macOS Docker 版本 4.33 的已知问题](https://github.com/docker/for-win/issues/14258)，请考虑回滚到 4.32 或升级到 4.35。

***

`错误：解决失败：ubuntu:22.04：无法解析 http://docker.io/library/ubuntu:22.04 的源元数据：授权失败：获取 oauth 令牌失败`

* 你位于中国吗？你的连接可能会被防火长城中断。尝试在命令行中手动运行 `docker pull ubuntu:22.04` （按 Win+R 打开命令行，然后输入 `cmd` 并按回车）。

***

`System.IndexOutOfRangeException：索引超出了数组的界限。`

* 如果你是通过下载 ZIP 文件安装我们的 Unity 快速入门插件，Unity Editor 缓存可能已损坏。尝试删除你的插件副本，并使用 git URL 或从 Unity 资产商店安装。由于会随其他源自动包含，现在你应该不再需要 Newtonsoft.JSON 包。

***

我的 Docker 镜像大小非常大（超过 1GB）/ 很小（低于 100MB），这样可以吗？

* 在某些情况下这可能没问题，只要你能运行服务器并成功连接（见 [#id-4.-test-your-server-locally](#id-4.-test-your-server-locally "mention")）。如果不是这种情况，请考虑检查你的构建选项，将其重置为默认值，然后逐步添加选项，看看它们如何影响构建大小。另见 [#optimize-server-build-size](#optimize-server-build-size "mention").

***

我遇到了文档中任何地方都没有提到的其他问题。

* 首先，请尝试 [更新你的 Edgegap 插件](https://github.com/edgegap/edgegap-unity-plugin?tab=readme-ov-file#update-the-plugin-in-unity) ，因为我们可能已经发布了修复。如果这仍然无效，请通过我们的 [社区 Discord](https://discord.gg/NgCnkHbsGp) 联系我们，我们会立即与你一起调查。

</details>

## 🧪 4. 在本地测试服务器

让我们先在本地（在你的机器上）尝试部署并连接游戏客户端，以确保服务器映像在我们上传和部署（可能需要一些时间）之前能正常工作。

☑️ 你可以配置以下选项（或保留默认值）：

* **服务器镜像标签** 来自上一步。
  * 默认为你使用该插件构建的最后一个标签。
* **可选的 docker run 参数** 可用于暴露多个端口，或在 macOS 机器上运行你的镜像。
  * 如果需要，你可以为容器发布多个端口，只需为每个端口添加参数 `-p {internal port}/{protocol}` ，例如 `-p 8080/tcp -p 7777/udp` 以发布并映射你的服务器端口 `8080` 到一个随机的外部端口，用于 TCP 连接，同时将服务器端口 `7777` 映射到一个随机的外部端口，用于 UDP 连接。 **在你的 Transport 或特定于 netcode 的设置中查找服务器端口配置。**
  * 如果你使用的是 ARM 架构的机器（macOS M1、M2、M3 等），你应该会在 Optional docker build parameters 中看到包含这个可选参数： `--platform=linux/amd64` .

☑️ 一旦你对配置满意，就点击 **部署本地容器**，等待进程完成，并确认你的 Unity 控制台中没有新错误。完成此步骤后，将会有一个 **新容器被启动** 在你的开发机器上。

{% hint style="info" %}
更多详情请参见 Docker Desktop / Containers，或 Docker CLI 命令 `docker ps` .
{% endhint %}

☑️ 现在该 **将你的 Unity Editor 游戏客户端连接到本地 Docker 容器** 以验证你的服务器镜像是否正常工作。找到你的 netcode 客户端设置并输入：

* `localhost` 或 `0.0.0.0` （在大多数情况下等同）代替服务器 IP，
* Docker Desktop / Containers / edgegap-server-test 中找到的随机外部端口值。

<figure><img src="https://3334189208-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2FCDGTUe5ests3DI3u9rTV%2Fimage.png?alt=media&amp;token=8c4799d8-0622-4142-91a5-93fd1816149c" alt=""><figcaption></figcaption></figure>

☑️ 一旦你确认可以连接到本地服务器容器并且能够正常游戏，就可以删除该容器 🗑️ 以释放机器上的资源供其他程序使用。

✅ 现在你可以进入下一步了。

<details>

<summary>故障排查与常见问题</summary>

我无法使用 Unity Editor 游戏客户端连接到本地 Docker 容器。

* 首先，确保容器状态为 Up，而不是 Restarting 或 Exited，这表示存在运行时异常。如果你的容器没有运行，请通过 Docker Desktop 的 Containers 标签页（点击你的容器）或使用 `docker logs {container_id} --timestamps` 通过 docker CLI 查看其日志。
* 接下来，请确认你的服务器构建中的 Network Manager 端口设置与 **可选的 docker run 参数**中发布的端口一致。如果不一致，请尝试重置或手动更改此输入字段的值以匹配 `{container}` 端口与 Network Manager 设置一致。在你的 netcode 设置中查找协议。
* 最后，确认你的 Unity Editor 游戏客户端 netcode 设置使用的是 **可选的 docker run 参数** 中发布的端口（见上方截图）。

***

`（段错误）- 已转储核心文件`

* 如果你使用的是 ARM 架构的机器（macOS M1、M2、M3 等），你应该会在 Optional docker build parameters 中看到包含这个可选参数： `--platform=linux/amd64` 。如果没有，请尝试重置此输入字段的值。

***

`未在 SceneObjects 中找到 SceneId 9120233082191360994。`

* 这可能意味着你尝试加载的场景没有被正确包含在构建中，这是旧版本插件中的一个已知问题。要解决此问题，请尝试更新你的 netcode 集成版本或 [更新你的 Edgegap 插件](https://github.com/edgegap/edgegap-unity-plugin?tab=readme-ov-file#update-the-plugin-in-unity).

***

`http2: server: error reading preface from client //./pipe/docker_engine: 文件已关闭`

* 这是一个 [Windows 版 Docker Desktop 较旧版本中的已知问题](https://github.com/docker/for-win/issues/13611)。请更新你的 Docker Desktop 应用并再次尝试容器化。

***

`Curl 错误 35：证书握手失败。致命错误。UnityTls 错误代码：7`

* 此错误表示根 SSL 证书验证问题，是旧版本插件中的一个已知问题。要解决此问题，请尝试 [更新你的 Edgegap 插件](https://github.com/edgegap/edgegap-unity-plugin?tab=readme-ov-file#update-the-plugin-in-unity).

</details>

## ☁️ 5. 上传到 Edgegap

是时候将您的服务器上线了！既然您的镜像现在可以成功托管玩家，我们就可以将其上传到 Edgegap 并开始在世界任何地方运行。在本指南中，我们将使用 [**Edgegap 的容器注册表**](/zh/learn/advanced-features/edgegap-container-registry.md) （镜像的存储）。

☑️ 你可以配置以下选项（或保留默认值）：

* **应用名称** 在 Edgegap 上可以与镜像名称一致，也可以自定义。
  * 我们暂时选择复制你的镜像名称。
* **服务器镜像** 来自步骤 [#id-3.-containerize-server](#id-3.-containerize-server "mention").

{% hint style="success" %}
在你的机器中查找存储的任何镜像名称和标签 **Docker Desktop / 镜像**.
{% endhint %}

☑️ 一旦你对配置满意，就点击 **上传镜像并创建应用版本**，等待进程完成，并确认你的 Unity 控制台中没有新错误。

☑️ 你将会进入我们的 [仪表板](https://app.edgegap.com/)，你可以在其中配置可选设置。完成此步骤后，将会有一个 [新的应用版本被创建](https://app.edgegap.com/application-management/applications/list)，并且你的 [构建产物将被标记并上传到 Edgegap 的容器注册表](https://app.edgegap.com/registry-management/repositories/list).

* **应用版本** 在 Edgegap 上可以与你的标签一致，也可以自定义。
  * 时间戳是应用版本名称的一个很好的选择，例如 `2024.01.30-16.50.20-UTC` .
  * 多个应用版本可能指向同一个镜像标签，例如 `v1.1.0` 和 `dev` .
  * 稍后了解更多关于 [应用与版本](/zh/learn/bian-pai/application-and-versions.md) 的信息。

☑️ 现在系统会提示你为新的应用版本定义一个端口。确保将其设置为与你在步骤 [#id-4.-test-server-locally](#id-4.-test-server-locally "mention") 中从 Transport 或特定于 netcode 的设置中使用的相同服务器端口值。

✅ 现在你可以进入下一步了。

<details>

<summary>疑难解答与常见问题</summary>

`被拒绝：添加 756.6 MiB 的存储资源，更新为当前使用量 4.3 GiB 后将超过配置的上限 4.7 GiB` , `在引用 "layer-sha256:--------" 上提交失败：对 https://registry.edgegap.com/ 的 PUT 请求返回了意外状态`

* 看起来您在以下位置的镜像存储空间已用尽 [容器注册表](https://app.edgegap.com/registry-management/repositories/list)。请考虑删除未使用的构建产物（如果有）或优化服务器构建体积。如果使用自定义 Dockerfile 或 .dockerignore，您可能将一些不需要的文件复制到镜像中。

***

`您已达到应用数量上限 2` , `无法更新 docker 标签/版本：您已达到应用版本数量上限 2`

* 您已达到我们免费等级的限制，请考虑升级您的账户。或者，您可以通过我们的界面删除现有资源 [仪表板](https://app.edgegap.com/).

***

我的新应用版本未在插件/扩展中列出。

* 请确保您在上一步已完成应用版本创建表单。

</details>

## 🚀 6. 部署到云端

这是本指南的最后一步，完成后您将在 Edgegap 云上部署一个服务器，来自世界任何地方的玩家都可以连接到该服务器。

☑️ **选择一个应用程序和版本** 从先前的步骤部署。

☑️ 一旦准备好，请点击 **部署到云端**，等待达到 [/pages/5e7e2169ca3822647d4607dfc1d3487ebcc0836c#id-3.-deployment-ready](https://docs.edgegap.com/zh/pages/5e7e2169ca3822647d4607dfc1d3487ebcc0836c#id-3.-deployment-ready "mention")。完成此步骤将导致 [一个新的部署被启动](https://app.edgegap.com/deployment-management/deployments/list) 在您的 Edgegap 帐户上。

☑️ 验证控制台输出中没有新的错误。同时确保您的 [部署](/zh/learn/bian-pai/deployments.md#container-logs) 没有显示任何错误，并且您的 [部署](/zh/learn/bian-pai/deployments.md#container-metrics) 未显示 100% 的资源利用率（vCPU 或内存），否则新的玩家连接可能会被拒绝，或您的服务器可能会陷入重启循环。请参阅下面的故障排除步骤以解决任何问题。

☑️ 现在我们将进行最后的测试，并 **将你的 Unity Editor 游戏客户端连接到云端部署**。输入来自部署的游戏客户端连接详细信息：

* **主机** **URL** 指向服务器 IP，通常在 `NetworkManager` 组件中。
* **外部端口** 映射到 [服务器的内部监听端口](/zh/learn/bian-pai/application-and-versions.md#port-mapping)，通常在 Transport 组件中。

<figure><img src="https://3334189208-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2Fz9xjzvZwKSIp9IeC9qo8%2Fimage.png?alt=media&amp;token=e3f345ac-848d-4469-b66f-3655cd393cf3" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
您在 Edgegap 云上的部署的外部端口将随机选择，以便在潜在攻击者（黑客）造成损害之前减缓并检测到他们。
{% endhint %}

{% hint style="warning" %}
**测试时请禁用 VPN** 以获得更真实的条件并接收一个 [低延迟部署](/zh/learn/bian-pai/deployments.md#server-placement).
{% endhint %}

☑️ 一旦您确认可以无问题连接到您的部署并完成测试， **停止您的部署** 以释放您账户中的容量用于下一次构建。

* 如果您遇到问题， [检查您部署的仪表板日志](https://app.edgegap.com/deployment-management/deployments/list).
* 如果您无法找出问题，我们会在我们的频道等着您， [社区 Discord](https://discord.gg/NgCnkHbsGp) 遇到困难？我们在我们的

🙌 恭喜您在 Edgegap 上完成首次部署！如果您想了解更多，请继续阅读。

<details>

<summary>故障排查与常见问题</summary>

无法连接客户端到服务器 - `请求超时。` , `请求超时` , `连接失败` ，或者 `端口验证失败`

* 首先，确保部署状态为 Ready，并且部署日志中没有运行时异常或错误。如果你的部署已停止，请在我们的 [仪表板](https://app.edgegap.com/deployment-management/deployments/list).
* 如果你使用的是 Mirror netcode，你需要在你的 [“Auto Start Server”](https://mirror-networking.gitbook.io/docs/hosting/edgegap-hosting-plugin-guide#build-and-push) 中选择 `NetworkManager` ，然后重新构建、推送并重新部署你的服务器。
* 如果你使用的是 FishNet netcode，你需要启用 [“Start on Headless”](https://fish-networking.gitbook.io/docs/manual/components/managers/server-manager#settings-are-general-settings-related-to-the-servermanager) 在你的 `ServerManager`，然后重新构建、推送并重新部署你的服务器。
* 如果你使用的是 Photon Fusion 2 netcode，请确保你的服务器传递了部署的公网 IP、外部端口以及 `roomCode` 在服务器端，以及客户端中相同的房间代码，在 [“NeworkRunner.StartGame”](https://doc.photonengine.com/fusion/current/manual/network-runner#creating-or-joining-a-room) 参数 `StartGameArgs`。部署 ID（例如 `b63e6003b19f`）是一个很好的选择，因为它在全局范围内唯一，并且客户端可通过 [Matchmaker](/zh/learn/pi-pei/matchmaker-in-depth.md) 和 [深入了解](/zh/learn/pi-pei/matchmaker-in-depth.md#injected-environment-variables).
* 接下来，请确认你的服务器构建中的 netcode 设置里的端口设置与 [应用版本](https://app.edgegap.com/application-management/applications/list)中的内部端口一致。你可以通过编辑 [应用版本](https://app.edgegap.com/application-management/applications/list) 而无需重新构建来更改端口映射。在你的 netcode 集成中查找你的协议。
* 请确保你的游戏客户端连接到 **外部端口** ，该值显示在你的部署详情页面上，由于安全原因，此值始终是随机的。
* 如果你在 netcode 集成中使用安全 WebSocket（WSS）协议，请确保你的 [应用版本](https://app.edgegap.com/application-management/applications/list) WSS 端口的端口配置已启用 TLS 升级。
* 你位于中国并且正在使用 [智能舰队](https://docs.edgegap.com/docs/deployment/session/fleet-manager/fleet)吗？你的连接可能会被防火长城阻止。请考虑在你的舰队中添加一台位于中国的服务器，或者使用 VPN 连接。

***

我的部署停止/重启了，而且我再也无法访问它的日志。

* 如果服务器进程因异常崩溃，我们的系统会尝试自动重启服务器。请考虑 [在本地测试你的服务器](#id-4.-test-your-server-locally) 以找出根本原因。
* 我们只会在部署期间保留日志，如果你希望在部署停止后检查日志，请 [集成第三方日志存储](https://docs.edgegap.com/docs/deployment/endpoint-storage).
* 参见 [/pages/5e7e2169ca3822647d4607dfc1d3487ebcc0836c#id-5.-deployment-stopped](https://docs.edgegap.com/zh/pages/5e7e2169ca3822647d4607dfc1d3487ebcc0836c#id-5.-deployment-stopped "mention") 以了解导致部署停止的所有原因。

***

我的部署在 X 分钟后自动停止了。

* 免费套餐部署有 60 分钟限制，请考虑升级你的账号。
* 根据我们的服务器清理策略，为了进行基础设施维护，并防止在部署未正确关闭时产生意外费用，所有部署将在运行 24 小时后终止。对于长期运行的服务器，请考虑使用 [私有舰队](/zh/learn/bian-pai/si-you-jian-dui.md) 与 [持久化](/zh/learn/bian-pai/chi-jiu-hua.md).
* 参见 [/pages/5e7e2169ca3822647d4607dfc1d3487ebcc0836c#id-5.-deployment-stopped](https://docs.edgegap.com/zh/pages/5e7e2169ca3822647d4607dfc1d3487ebcc0836c#id-5.-deployment-stopped "mention") 以了解导致部署停止的所有原因。

***

我的部署已就绪，但随后几分钟内我无法连接。

* 一旦部署就绪，你的游戏引擎初始化就会开始。这个过程可能需要从几秒到几分钟不等，在此期间服务器不会接受玩家连接。
* 考虑优化你的服务器初始化，以缩短这段时间。
* 游戏客户端应以 1 秒间隔在有限时间内重试连接（取决于你的初始化时长），之后应返回匹配流程。
* 考虑添加一个加载场景，以便服务器可以在与客户端同步状态的同时进行初始化（以及在 Unreal Engine 中进行旅行）。

***

我的 Meta Quest 设备报错 `HTTP 0：无法解析目标主机` .

* 当为 Android 目标构建 Unity 应用时，你的 Internet Access 权限可能会从输出的 APK 客户端构建产物中自动移除。
* 重新添加权限（需要之后重新构建客户端）：
  * 项目设置 / OpenXR / :gear: Meta Quest 支持 / 强制移除 Internet 权限（取消勾选）。
  * 玩家设置 / Internet Access（设为 require）。

***

如果玩家离开我的部署会发生什么？

* 默认情况下，服务器不会拒绝玩家连接。玩家身份验证由你的开发者负责，因为可以使用许多不同的方法和玩家身份验证提供商。
* 游戏客户端可能会在本地存储连接信息，以便在客户端意外崩溃时尝试重新连接。
* 要允许玩家加入进行中的游戏，可以考虑使用 [深入了解](/zh/learn/pi-pei/matchmaker-in-depth.md#backfill) 或 [会话](https://docs.edgegap.com/docs/deployment/session).

***

我的服务器在就绪后显示 100% CPU 利用率。

* 这可能不是问题，因为游戏引擎在服务器初始化期间往往会执行高 CPU 负载操作。如果在部署开始后 2-3 分钟 CPU 使用率仍未下降，你可能需要优化服务器或增加应用版本资源。
* 降低 tick rate 可能会影响 CPU 使用率，因为服务器执行的消息操作更少。
* 如果你使用的是 Mirror netcode，你需要在你的 [“Auto Start Server”](https://mirror-networking.gitbook.io/docs/hosting/edgegap-hosting-plugin-guide#build-and-push) 中选择 `NetworkManager` ，然后重新构建、推送并重新部署你的服务器。
* 如果你使用的是 FishNet netcode，你需要启用 [“Start on Headless”](https://fish-networking.gitbook.io/docs/manual/components/managers/server-manager#settings-are-general-settings-related-to-the-servermanager) 在你的 `ServerManager`，然后重新构建、推送并重新部署你的服务器。
* 在免费套餐中，你最多只能使用 1.5 vCPU 和 3GB 内存（RAM）。
* 你可以编辑现有版本的分配资源，或者复制你的版本并在新副本中修改资源。两者都不需要重新构建服务器。

***

我的部署反复重启并显示错误 `OOM kill`

* 这是由超出分配内存量引起的。考虑使用对象池、压缩或移除场景中不需要的对象来优化内存使用。
* 确保你的项目正在加载包含你的 `NetworkManager` 的默认场景，并且该场景已包含在 Unity 的 Build Settings 中。
* 在免费套餐中，你最多只能使用 1.5 vCPU 和 3GB 内存（RAM）。
* 你可以编辑现有版本的分配资源，或者复制你的版本并在新副本中修改资源。两者都不需要重新构建服务器。

***

有时，我服务器的内存（RAM）使用会突然飙升到很高的值，这会有问题吗？

* 只要你没有超出分配的应用版本内存量，这就不是问题。
* 超出分配的应用版本内存量将导致 `OOM kill` （见上文）。

***

我的服务器性能会受到同一台机器上运行的其他服务器影响吗？

* 不会，我们的平台会确保分配的资源不会被其他工作室或共享基础设施上的其他服务器使用。在 Edgegap 上，不会有“吵闹的邻居”。

</details>

## 👉 下一步

一旦你有了可用的客户端/服务器设置，请确保 **保存你的项目副本** （使用诸如 git 之类的版本控制软件），以便在遇到问题时总能追溯你的步骤。

继续阅读以了解更多与服务器生命周期和可发现性相关的主题。

{% hint style="info" %}
如果你需要帮助， [请通过 Discord 联系我们](https://discord.gg/MmJf8fWjnt)。关于实时游戏支持，请查看我们的 [工单系统](https://edgegap.atlassian.net/servicedesk/customer/portal/3).
{% endhint %}

### 停止部署

一旦比赛结束（或玩家离开），就可以停止你的部署以节省成本。 [空置或仅部分填充的部署会不必要地增加你的成本！](https://edgegap.com/blog/how-session-fill-rate-affects-your-multiplayer-hosting-costs)

{% hint style="success" %}
导入我们的 `DeploymentAgent`  Unity SDK 示例，以便 **轻松可靠地停止服务器**.
{% endhint %}

{% hint style="warning" %}
连接你的 [端点存储](/zh/docs/endpoint-storage.md) 以保存部署日志，否则它们将被删除！
{% endhint %}

### 注入变量

通过访问注入的环境变量，读取部署 ID、服务器 IP 地址、服务器位置等有用信息。每个部署都会自动包含：

* [部署变量](/zh/learn/bian-pai/deployments.md#injected-environment-variables) - 由 Edgegap 自动提供，
* [匹配变量](/zh/learn/pi-pei/matchmaker-in-depth.md#injected-environment-variables) - 在使用时由 Edgegap 自动提供， [匹配](/zh/learn/pi-pei.md),
* [应用版本变量](/zh/learn/bian-pai/application-and-versions.md#injected-variables) - 由你配置的自定义键值对。

{% hint style="success" %}
导入我们的 `DeploymentAgent`  Unity SDK 示例，以便 **轻松读取强类型变量**.
{% endhint %}

### 会话自动化

{% hint style="warning" %}
**手动启动你的部署，复制 URL 和端口在实时游戏中行不通。**
{% endhint %}

使用以下任一方式，自动化热门游戏流程，以管理会话并按需扩展：

{% columns %}
{% column width="33.33333333333333%" %}
[匹配](/zh/learn/pi-pei.md):

* 更短的回合
* 按需对局
* 技能评级和/或\
  自定义规则
  {% endcolumn %}

{% column width="33.33333333333333%" %}
[服务器浏览器](/zh/learn/fu-wu-qi-liu-lan-qi.md):

* 持久模式或回合制
* 社交区域枢纽
* 自动分配和/或\
  自定义搜索
  {% endcolumn %}

{% column width="33.33333333333333%" %}
自定义后端：

* 迁移实时游戏
* [使用 v2 API 部署](/zh/docs/api/zhuan-yong-fu-wu-qi.md)
* [监控 Webhooks](/zh/learn/bian-pai/deployments.md#webhooks)
  {% endcolumn %}
  {% endcolumns %}

### 优化构建

**只重新构建自上次构建以来发生变化的资源。**

考虑使用 [Unity 的增量构建](https://docs.unity3d.com/Manual/incremental-build-pipeline.html) 来加快构建时间。

* 考虑使用 [Unity 的增量构建](https://docs.unity3d.com/Manual/incremental-build-pipeline.html) 来加快构建时间。

**只包含服务器运行绝对需要的内容。**

* 在镜像中复制未使用的文件会导致镜像臃肿、上传时间更长、缓存速度更慢，以及服务器整体启动更慢。 [查看 Docker 镜像优化建议](https://docs.docker.com/build-cloud/optimization/#dockerignore-files).

**禁用网格的静态批处理以减小镜像大小。**

* [禁用静态批处理可加快构建、上传和部署。](https://docs.unity3d.com/Manual/DrawCallBatching.html)

**压缩网格以减小镜像大小。**

* [将网格压缩设置为 High 以加快构建、上传和部署。](https://docs.unity3d.com/6000.0/Documentation/Manual/compressing-mesh-data-optimization.html)
* 顶点压缩不会影响镜像大小。

**实现资源的条件式延迟加载。**

* 通过以下方式排除仅客户端资源： [将纹理和网格的 CPU 读/写设置为禁用](https://docs.unity3d.com/6000.0/Documentation/Manual/dedicated-server-optimizations.html).
* 考虑使用 [Unity Addressables](https://docs.unity3d.com/Packages/com.unity.addressables@2.1/manual/index.html) 用于客户端构建，通过以下方式加快构建和部署： [按需加载资源](https://docs.unity3d.com/Packages/com.unity.addressables@1.19/manual/LoadingAddressableAssets.html)，或者通过检查是否存在以下内容来在服务器构建中跳过加载某些资源： [部署](/zh/learn/bian-pai/deployments.md#injected-environment-variables).

**考虑使用** [**多阶段 Docker 构建（链接）**](https://docs.docker.com/build/building/multi-stage/)**.**

* 将大型服务器依赖项拆分到单独的镜像中，以便在多阶段构建中复用。Docker 会缓存每一层，并直接复用之前的版本，除非特别指示，否则会跳过上传这部分，从而为你节省带宽和等待上传完成的时间。
* 如果你不确定为什么某个 Dockerfile 命令会报错，尝试在本地调试。在问题发生之前创建一个新阶段（再添加第二个 `FROM` 命令），使用 `--target` 来指示构建过程在有问题的阶段停止，然后 `docker exec -it {container} /bin/bash` 进入容器内的交互式终端。之后，你可以在基础镜像中使用 shell 命令进一步调查（例如 `top` 在 Ubuntu 上）。

### 自定义镜像

我们也支持为需要对镜像有更多控制的用户添加自己的 Dockerfile，例如为了优化构建大小、移除多余依赖，或需要更复杂的启动流程。你可以选择在步骤中提供自定义 Dockerfile 的路径 [#id-3.-containerize-server](#id-3.-containerize-server "mention")。接下来我们将分享一些“自己动手”的技巧和最佳实践。

**始终确保你使用的是一个可正常运行的服务器构建版本。**

* 在断定某个问题与自定义 Dockerfile 有关之前，请确保你的服务器构建能够启动，并且游戏引擎中的构建过程没有抛出任何异常或错误。

**上传前务必先在本地测试。**

* 在本地测试你的镜像可以为你节省大量等待上传完成的时间。而且它完全免费 ✨，因为不需要任何 Edgegap 资源。
* 在本地测试时，请务必正确设置内部端口：

  ```bash
  docker run \
    -p 7777/udp \
    -e ARBITRIUM_PORTS_MAPPING='{"ports":{"gameport":{"internal":7777}}}' \
    'registry.edgegap.com/<repository>:<tag>'
  ```

**确保你已经掌握了基础内容。每个 Dockerfile 都需要一些基本的必需命令：**

* `FROM {image}` 是你的基础镜像，我们通常使用长期支持的 Linux，但任何基于 Linux 的基础镜像都可以。这些通常是存储在 Docker Hub 上的公共镜像。Dockerfile 参考文档见此。 [Dockerfile 参考文档见此](https://docs.docker.com/reference/dockerfile/#from).
* `COPY {source} {destination}` 用于将你主机上的 Linux 服务器构建复制到镜像内部，以便之后可以启动它。 [Dockerfile 参考文档见此](https://docs.docker.com/reference/dockerfile/#copy).
* `USER {user}` 应该跟在一个 [useradd (ubuntu) 命令](https://manpages.ubuntu.com/manpages/bionic/man8/useradd.8.html) 之后，最好不要把所有东西都以 `root` 的身份运行，以便更安全。 [Dockerfile 参考文档见此](https://docs.docker.com/reference/dockerfile/#user).
* `CMD {command}` 将是最后一行，很可能会调用一个 `StartServer.sh` 或某种启动脚本，以确保在一切设置完成后你的服务器能够正确初始化。 [Dockerfile 参考文档见此](https://docs.docker.com/reference/dockerfile/#cmd).
* 不要使用 `VOLUME` - 你将无法通过这种方式在 Edgegap 上挂载任何本地存储，请考虑改用我们的 Endpoint Storage 功能并使用 S3 存储桶，参见 [Endpoint Storage](https://docs.edgegap.com/docs/deployment/endpoint-storage),
* `EXPOSE 7777/UDP`  不是必需的！这实际上不会让容器外部访问内部服务器端口，它只是给开发者的一个提示，而该端口需要
  * 在本地测试时通过以下方式发布： `docker run <image> -p 7777/udp` ,
  * 或映射到 [Edgegap Port Mapping](/zh/learn/bian-pai/application-and-versions.md#other-parameters-optional).

**尽可能将参数的声明延后到最后一刻。由于服务器构建时间较长，可配置性 > 可组合性。** [**将此方法应用到 Dockerfile 命令中，以更快地构建和上传。**](https://medium.com/@esotericmeans/optimizing-your-dockerfile-dc4b7b527756)

* 场景：你需要定义诸如部署阶段、版本、游戏模式、地图、每台服务器的玩家数量、备份频率或类似的参数。
* 糟糕的方案：为参数的每一种组合都创建一个单独的镜像。你会把所有时间都花在重新构建镜像上，而这种方法带来的好处却非常有限。
* 更好的方案——在需要时再替换配置参数：
  1. 部署参数——在部署前才提供——例如作为环境变量传递的匹配选择器，或者你的自定义会话管理系统在部署时传递环境变量，
  2. 版本参数——在同一应用版本的所有部署中共享——例如部署阶段、制品标签、第三方密钥和端点等；然后
  3. 一个单一镜像——在启动时包含并加载所有配置选项。

**不要在 Edgegap 部署中运行数据库。**

* Edgegap 部署并非为长时间运行的进程而设计，可能会在运行很久后未经事先通知而被终止。以这种方式运行的数据库（即使是分布式的）也可能被终止，并导致不可逆的数据丢失。如果你需要数据库，请考虑使用第三方 DBaaS。
* 考虑使用我们的 [托管集群](https://app.edgegap.com/cluster-management/clusters/list) 来托管数据库和长时间运行的服务。

{% hint style="info" %}
遇到难题了？我们在我们的 [社区 Discord](https://discord.gg/MmJf8fWjnt) 中提供帮助，很乐意协助。
{% endhint %}
