> 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/unreal-engine.md).

# Unreal Engine - 快速入门

在 Edgegap 上部署你的第一个 Unreal Engine 专用服务器。一份涵盖构建、上传和全球部署的实操指南，适用于多人游戏。

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

使用 Docker Desktop 构建是入门最快、最简单、也最可靠的方法。

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

## ✔️ 准备工作

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

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

<details>

<summary><a href="https://www.docker.com/products/docker-desktop/">安装 Docker Desktop 和 Docker Edgegap 扩展</a></summary>

* [从官方来源安装 Docker Desktop](https://www.docker.com/products/docker-desktop/) （无需账户）。
* 安装完成后重启计算机。
* 进入 设置 ⚙️ > 扩展 > 启用 Docker 扩展。
* [从官方 Docker Marketplace 安装扩展（点击此链接）。](https://www.docker.com/products/docker-desktop/)

</details>

<details>

<summary><a href="https://open.docker.com/extensions/marketplace?extensionId=edgegap/docker-extension">安装 Edgegap Quickstart Docker 扩展</a></summary>

* 从 Docker Desktop / Extensions / Browse 安装，或 [使用链接](https://open.docker.com/extensions/marketplace?extensionId=edgegap/docker-extension).

<figure><img src="https://3334189208-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FsR0dHSFv9ymoC0DO5G8J%2Fuploads%2FraFWUCJWPZYvBMLieBUZ%2Fimage.png?alt=media&amp;token=186886ac-accb-421d-b560-3ccefa7f29cb" alt=""><figcaption></figcaption></figure>

</details>

<details>

<summary><a href="https://www.unrealengine.com/en-US/ue-on-github">在 GitHub 上获取对 Unreal Engine 资源的访问权限</a></summary>

* [注册一个 GitHub 账户。](https://github.com/)
* 导航到你的 [Unreal Engine 关联账户仪表板页面](https://www.epicgames.com/account/connections).
* 将 GitHub 账户与您的 Epic 账户关联。
  * 授权 Epic Games 访问您的 GitHub 账户。
  * 接受通过电子邮件发送的加入 Epic Games 组织的 GitHub 邀请。

</details>

<details>

<summary><a href="https://github.com/settings/tokens/new">生成 GitHub 个人访问令牌（经典）</a></summary>

* 仅启用权限 `[读取:软件包]` ,
* 生成令牌 - **请妥善保存此值，您将无法再次看到它**.

</details>

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

## ⚙️ 1. 配置项目 <a href="#id-1-configure-project" id="id-1-configure-project"></a>

无论您使用的是 Windows、Mac 还是 Linux 机器，您将 **需要为 Linux 运行时构建您的服务器**，因为如今大多数云提供商（包括 Edgegap）都运行在 Linux 上。别担心，不需要具备 Linux 知识。

{% hint style="warning" %}
不要在 Unreal Editor 中打包你的项目。不要手动安装 Linux 工具链。不要设置 `LINUX_MULTIARCH_ROOT` . 不要从源代码构建 Unreal Engine。 **我们的扩展会为你完成这一切。**
{% endhint %}

☑️ 首先 **验证你的 Unreal Engine 版本** - 已使用你项目文件中的值预填充。

☑️ **输入 GitHub 用户名和** [**PAT**](#user-content-fn-1)[^1] 来自 [#preparation](#preparation "mention")，以从 GitHub 下载依赖项。

<details>

<summary><a href="https://github.com/settings/tokens/new">生成 GitHub 个人访问令牌（经典）</a></summary>

* 仅启用权限 `[读取:软件包]` ,
* 生成令牌 - **请妥善保存此值，您将无法再次看到它**.

</details>

☑️ **禁用 Unreal Engine 版本兼容性检查** 用于专用服务器和 **设置 `IpNetDriver` 作为默认驱动或备用驱动** 用于复制网络：

{% hint style="warning" %}
确保 **输入你的 `DefaultServerTarget`  在此片段的末尾**!
{% endhint %}

<pre data-title="Config/DefaultEngine.ini"><code><a data-footnote-ref href="#user-content-fn-2">[ConsoleVariables]</a>
net.IgnoreNetworkChecksumMismatch=1
net.CurrentHandshakeVersion=2
net.MinHandshakeVersion=2
net.VerifyNetSessionID=0
net.VerifyNetClientID=0

<a data-footnote-ref href="#user-content-fn-3">[/Script/Engine.GameEngine]</a>
!NetDriverDefinitions=ClearArray
+NetDriverDefinitions=(DefName="GameNetDriver",DriverClassName="OnlineSubsystemUtils.IpNetDriver",DriverClassNameFallback="OnlineSubsystemUtils.IpNetDriver")

<a data-footnote-ref href="#user-content-fn-4">[/Script/OnlineSubsystemUtils.IpNetDriver]</a>
MaxClientRate=1000000000
MaxInternetClientRate=1000000000
InitialConnectTimeout=120.0
MaxNetTickRate=60
NetServerMaxTickRate=60

<a data-footnote-ref href="#user-content-fn-5">[/Script/BuildSettings.BuildSettings]</a>
DefaultServerTarget=LyraServer
</code></pre>

☑️ **重启 Unreal Engine** 以重新加载最新更改。

☑️ **创建专用服务器目标脚本** 通过复制你的 `<PROJECT>Editor.Target.cs` 项目根文件夹中的文件并将副本重命名为 `<PROJECT>Server.Target.cs`.

☑️ **替换任何对** 单词 **`Editor`** **为** **`Server`** 在你的服务器目标脚本中。

☑️ **修改服务器构建默认设置** 通过编辑你的服务器目标脚本：

<pre data-title="Source/<PROJECT>Server.Target.cs"><code>bOverrideBuildEnvironment = true;
<a data-footnote-ref href="#user-content-fn-6">bUseLoggingInShipping = true;</a>
<a data-footnote-ref href="#user-content-fn-7">bUseChecksInShipping = false;</a>
<a data-footnote-ref href="#user-content-fn-8">bBuildWithEditorOnlyData = false;</a>
<a data-footnote-ref href="#user-content-fn-9">bUsesSlate = false;</a>
<a data-footnote-ref href="#user-content-fn-10">bCompileCEF3 = false;</a>
</code></pre>

✅ 你现在可以继续下一步。

<details>

<summary>可选：Steam 集成</summary>

要 **集成 Steam**，使用 `IpNetDriver` 作为默认网络驱动并确认 [适用于 Linux 的 64 位 steamclient.so](https://developer.valvesoftware.com/wiki/SteamCMD#Ubuntu) 已复制到镜像中的路径 `/home/ubuntu/.steam/sdk64/` .

{% hint style="success" %}
添加 `steamclient.so`  Linux 库，只需使用我们的 [docker 扩展](/zh/unreal-engine.md).
{% endhint %}

<a href="https://github.com/edgegap/edgegap-unreal-buildutils/raw/refs/heads/main/steamclient.so" class="button secondary" data-icon="square-down">下载 steamclient.so</a>

<pre class="language-docker" data-title="Dockerfile"><code class="lang-docker">...
<a data-footnote-ref href="#user-content-fn-11">RUN mkdir -p /home/ubuntu/.steam/sdk64</a>
<a data-footnote-ref href="#user-content-fn-12">COPY ./steamclient.so /home/ubuntu/.steam/sdk64/steamclient.so</a>
<a data-footnote-ref href="#user-content-fn-13">RUN chmod 755 /home/ubuntu/.steam/sdk64/steamclient.so</a>
...
</code></pre>

{% hint style="warning" %}
**请确保禁用 Steam 网络功能，该功能通过 Steam Relay 发送数据包，可能导致连接问题或延迟峰值。** 这不会妨碍您使用其他 Steamworks 功能，例如排行榜、成就、语音或在 Steam 商店发布您的游戏。
{% endhint %}

<pre data-title="Config/DefaultEngine.ini"><code>[OnlineSubsystemSteam]
bUseSteamNetworking=false
bAllowP2PPacketRelay=false
<a data-footnote-ref href="#user-content-fn-14">SteamDevAppId=480</a>
<a data-footnote-ref href="#user-content-fn-14">SteamAppId=480</a>
</code></pre>

</details>

## 🔧 2. 构建游戏服务器 <a href="#id-2-build-game-server" id="id-2-build-game-server"></a>

现在我们将构建并烹制你的项目，并将其打包为一个易于复用的 Docker 镜像。

{% hint style="warning" %}
不要在 Unreal Editor 中打包你的项目。不要手动安装 Linux 工具链。不要设置 `LINUX_MULTIARCH_ROOT` . 不要从源代码构建 Unreal Engine。 **我们的扩展会为你完成这一切。**
{% endhint %}

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

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

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

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

* **镜像名称** 是你自定义的唯一标识，用于在发布前标记你的服务器构建。
  * 通常，这会包含你的游戏名称——例如“my-game-server”。
* **镜像标签** 是指向镜像某个特定版本的标识符。
  * “构建产物”这个术语有时用于指代镜像的特定版本。
  * 时间戳是很好的默认标签选项，例如 `2024.01.30-16.23.00-UTC` .

☑️ **构建项目** 在你对配置满意后。完成此步骤后，你的本地 Docker 客户端中将新增一个包含 Linux 游戏服务器可执行文件的新镜像。

✅ 现在你可以继续下一步。

## 🧪 3. 本地测试服务器 <a href="#id-3-test-server-locally" id="id-3-test-server-locally"></a>

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

☑️ **选择你想在本地运行的镜像标签** （将下载远程镜像）。可选地，还可以提供更多 [docker run 参数](https://docs.docker.com/reference/cli/docker/image/build/#options) 来定制你的本地测试：

* `-p 7777:7777/udp` ——这是你本地容器的 [端口映射](/zh/learn/bian-pai/application-and-versions.md#port-mapping),
* `-e ARBITRIUM_PORT_GAMEPORT_INTERNAL=7777`  是一个 [环境变量](#environment-variables) 用于模拟真实的 Edgegap 部署，告诉你的游戏服务器为玩家连接监听哪个内部端口。

☑️ 当你对配置满意后，点击 **启动本地服务器**。完成此步骤后，将会在你的开发机器上 **启动一个新容器** 。

☑️ 现在是将你的 Unreal Engine 编辑器（PIE）游戏客户端连接到本地服务器容器的时候了。使用 `~`  （波浪号）打开 Unreal PIE 控制台，并使用 `open <ip>:<port>`:

* `ip`  = `localhost`  或 `127.0.0.1`  （在大多数情况下等同于），
* `port`  = Docker GUI 中容器的随机外部端口值。

<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>故障排除和 FAQ</summary>

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

* 首先，确保容器已启动，并且日志中没有运行时错误。
* 请验证你在 `docker run` 命令中的端口值是否匹配。
* 请确保你的游戏客户端连接到 **外部端口** ，该值显示在你的容器详情页面上，出于安全原因它将始终是随机的。
* 请确保你已按步骤中的说明重命名目标文件并配置游戏构建 [#id-1-configure-project](#id-1-configure-project "mention").

***

我的容器已启动，但之后几分钟我仍无法连接。

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

***

`警告：无法为绑定地址创建套接字`

* 请通过 Fab 资产商店安装 Epic 的 Steam 子系统插件。
* 当使用从 github 下载的 SteamCore 源码版本与 Edgegap Integration Kit（EGIK）时，由于 Epic Games 的插件分发政策，不包含 Epic 的 Steam 子系统插件。

***

我已连接，但屏幕完全是黑的。

* 确认你设置了正确的 **游戏默认地图** ，位于 **编辑 / 项目设置 / 地图与模式**.

</details>

## ☁️ 4. 发布到 Edgegap <a href="#id-4-publish-to-edgegap" id="id-4-publish-to-edgegap"></a>

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

☑️ **选择一个应用名称** 以在 Edgegap 上标记并分组相似镜像。

☑️ **选择你想发布的镜像标签** 和 **上传镜像**。完成此步骤后，你的服务器镜像将上传到 Edgegap Registry，并将创建一个新的 [应用版本](/zh/learn/bian-pai/application-and-versions.md) 将在你的网页浏览器中创建。 **请确保在提示时创建你的** [**端口映射**](/zh/learn/bian-pai/application-and-versions.md#port-mapping) **，** 并使用默认&#x503C;**.**

{% hint style="success" %}
发现了 bug，需要再次重建/发布？使用 **从源代码重建** 以 [#id-2.-build-game-server](#id-2.-build-game-server "mention") 和 [#id-4.-publish-to-edgegap](#id-4.-publish-to-edgegap "mention") **并使用当前扩展输入值快速完成。**
{% endhint %}

✅ 现在你可以继续下一步。

<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>

## 🚀 5. 部署到云端 <a href="#id-5-deploy-to-cloud" id="id-5-deploy-to-cloud"></a>

这是本指南的最后一步，完成后您将在 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 或内存），否则新的玩家连接可能会被拒绝，或您的服务器可能会陷入重启循环。请参阅下面的故障排除步骤以解决任何问题。

☑️ 现在我们将进行最终测试，并 **将你的 Unreal Engine 编辑器连接到云端部署**。请获取你的 **部署主机** 来替代服务器 IP，以及部署的 **外部端口**，在游戏客户端中打开 Unreal 控制台（波浪号 `~`）并输入 `open {host}:{port}` .

<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>故障排除和 FAQ</summary>

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

* 首先，确保部署状态为就绪，并且部署日志中没有运行时异常或错误。如果你的部署已停止，请在我们的 [仪表板](https://app.edgegap.com/deployment-management/deployments/list).
* 请验证你服务器构建的网络代码设置中的端口设置是否与你的 [应用版本](https://app.edgegap.com/application-management/applications/list)中的内部端口匹配。对于插件构建，端口会自动为你设置。你可以通过编辑 [应用版本](https://app.edgegap.com/application-management/applications/list) 无需重新构建。请在你的网络代码集成中查找对应协议。
* 请确保你的游戏客户端连接到 **外部端口** 该值显示在你的部署详情页上，出于安全原因它将始终是随机的。
* 请确保你已按步骤中的说明重命名目标文件并配置游戏构建 [#id-1-configure-project](#id-1-configure-project "mention").

***

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

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

***

`警告：无法为绑定地址创建套接字`

* 请通过 Fab 资产商店安装 Epic 的 Steam 子系统插件。
* 当使用从 github 下载的 SteamCore Integration Kit（SIK）源码版本与 Edgegap Integration Kit（EGIK）时，由于 Epic Games 的插件分发政策，不包含 Epic 的 Steam 子系统插件。

***

我已连接，但屏幕完全是黑的。

* 确认你设置了正确的 **游戏默认地图** ，位于 **编辑 / 项目设置 / 地图与模式**.
* 请确认 [Unreal Engine 版本兼容性检查已被禁用](#id-2.-configure-game-server-builds) 在 `DefaultEngine.ini`.

***

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

* 如果服务器进程因异常崩溃，我们的系统会尝试自动重启服务器。可以考虑先在本地测试你的服务器以找出根本原因。
* 我们只会在部署期间保留日志，如果你希望在部署停止后查看日志，请 [集成第三方日志存储](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") 以了解导致部署停止的所有原因。

***

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

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

***

我的服务器在变为就绪后显示 100% 的 CPU 占用。

* 这未必是问题，因为游戏引擎在服务器初始化期间往往会执行大量 CPU 密集型操作。如果 CPU 使用率在部署开始后的 2-3 分钟后仍未下降，你可能需要优化服务器或增加应用版本资源。
* 降低 tick 速率可以通过减少处理消息的数量来帮助控制 CPU 使用率。
* 在免费层中，你最多只能使用 1.5 vCPU 和 3GB 内存（RAM）。
* 你可以编辑现有版本分配的资源，或者复制你的版本并在新副本中修改资源。这两种方式都不需要重新构建服务器。

***

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

* 这是由于超出了分配的内存量造成的。可以考虑通过对象池、压缩，或移除场景中不需要的对象来优化内存使用。
* 在免费层中，你最多只能使用 1.5 vCPU 和 3GB 内存（RAM）。
* 你可以编辑现有版本分配的资源，或者复制你的版本并在新副本中修改资源。这两种方式都不需要重新构建服务器。

***

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

* 只要你保持在分配的应用版本内存额度内，这就不是问题。
* 超过分配的应用版本内存额度将导致 `OOM kill` （见上文）。

***

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

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

</details>

## 👉 后续步骤

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

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

### 停止部署

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

如果你遵循了本指南并使用我们的 Docker 扩展进行了构建，你可以直接调用方法 `FGenericPlatformMisc::RequestExit` 。我们已在打包后的镜像中添加了管理服务器进程的脚本，它会自动执行平滑的部署关闭。

如需自定义服务器生命周期管理，请修改我们的 [示例 `StartServer.sh`](https://github.com/edgegap/edgegap-unreal-buildutils/blob/main/StartServer.sh)  脚本。

{% hint style="info" %}
更喜欢在 Unreal 中管理生命周期？请参见 [开发者工具](/zh/unreal-engine/developer-tools.md#integration-kit) 自停止 API 蓝图。
{% 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-xi-tong/matchmaker-in-depth.md#injected-environment-variables) - 使用时由 Edgegap 自动提供， [匹配系统](/zh/learn/pi-pei-xi-tong.md),
* [应用版本变量](/zh/learn/bian-pai/application-and-versions.md#injected-variables) - 由你配置的自定义键值对。

{% hint style="success" %}
导入我们的 [开发者工具](/zh/unreal-engine/developer-tools.md#integration-kit) 以 **使用蓝图轻松读取带类型的变量**.
{% endhint %}

### 服务器性能分析

要了解并优化 Edgegap 上的服务器性能问题，请探索 [部署](/zh/learn/bian-pai/deployments.md#container-logs), [部署](/zh/learn/bian-pai/deployments.md#container-metrics)，以及更多 [部署](/zh/learn/bian-pai/deployments.md#dashboard-monitoring) 你可使用的工具。

你也可以将现有的 Unreal Engine 性能分析工具与 Edgegap 一起使用：

* [在你的 Unreal Engine 服务器中配置跟踪](https://dev.epicgames.com/documentation/en-us/unreal-engine/developer-guide-to-tracing-in-unreal-engine) （内置和自定义事件）：
  * 使用 `-tracefile`将跟踪保存到服务器磁盘，上传到第三方存储并离线分析，
  * 或者使用 [部署](/zh/learn/bian-pai/deployments.md#port-mapping) 用于内部端口 `1981` 通过 UDP 协议流式传输跟踪数据。
* 分析 [内存洞察](https://dev.epicgames.com/documentation/en-us/unreal-engine/memory-insights-in-unreal-engine) 和 [网络洞察](https://dev.epicgames.com/documentation/en-us/unreal-engine/networking-insights-in-unreal-engine) 和 [#optimize-server-builds](#optimize-server-builds "mention").

### 会话自动化

在与开发人员或 QA 团队测试新构建时，通常会跳过会话步骤，玩家直接连接到部署，同时对与会话相关的功能进行硬编码或禁用。这使开发迭代更快，并将会话副作用与服务器功能隔离开来。

{% hint style="warning" %}
**手动启动你的部署并粘贴 URL 和端口，无法满足实时游戏的需求。**
{% endhint %}

自动化以下热门游戏流程： [玩家会话](/zh/learn/bian-pai/wan-jia-hui-hua.md) 以及服务器扩缩容，可通过以下任一方式：

{% columns %}
{% column width="33.33333333333333%" %}
[匹配系统](/zh/learn/pi-pei-xi-tong.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 %}

### 优化构建

**配置资源分块，以将仅客户端资产与服务器资产隔离开。**

* 探索 [Epic 的资源分块技术和建议](https://dev.epicgames.com/documentation/en-us/unreal-engine/preparing-assets-for-chunking-in-unreal-engine) 。

**排除仅客户端使用、且服务器运行不需要的资产和插件。**

* 了解 [构建时资产和插件排除](https://dev.epicgames.com/community/learning/tutorials/Kp1k/unreal-engine-build-time-asset-and-plugin-exclusion).

**审查你的内容烹制策略。**

* 考虑 [即烹即用（COTF）](https://dev.epicgames.com/documentation/en-us/unreal-engine/build-operations-cooking-packaging-deploying-and-running-projects-in-unreal-engine#cookonthefly) 以延迟烹制客户端资产并加速服务器构建。

**实现关卡流式加载以减少运行时内存占用。**

* 如果你的设计让玩家大多集中在同一地图区域， [关卡流式加载可以将你的服务器内存使用量降低](https://dev.epicgames.com/documentation/en-us/unreal-engine/level-streaming-in-unreal-engine) 60% 以上，并提升客户端性能！

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

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

<details>

<summary>示例 <code>.dockerignore</code> 文件，以移除多余文件。</summary>

```docker
# 已编译的对象文件
*.slo
*.lo
*.o
*.obj

# 预编译头文件
*.gch
*.pch

# 已编译的动态库
*.so
*.dylib
*.dll

# Fortran 模块文件
*.mod

# 已编译的静态库
*.lai
*.la
*.a
*.lib

# 可执行文件
*.exe
*.out
*.app
*.ipa

# 这些项目文件可由引擎生成
*.xcodeproj
*.xcworkspace
*.sln
*.suo
*.opensdf
*.sdf
*.VC.db
*.VC.opendb

# 预编译资源
**/SourceArt/**/*.png
**/SourceArt/**/*.tga

# 构建
**/Build/*

# 白名单化 PakBlacklist-<BuildConfiguration>.txt 文件
!**/Build/*/
**/Build/*/**
!**/Build/*/PakBlacklist*.txt

# 不要忽略 Build 中的图标文件
!**/Build/**/*.ico

# 由编辑器生成的配置文件
**/Saved/*
**/Intermediate/*
**/DerivedDataCache/*
**/Binaries/*
**/Build/*
**/Releases/*
**/Packaged/*
```

</details>

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

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

### 自定义镜像

我们也支持为需要更多镜像控制的用户添加自己的 Dockerfile，例如为了优化构建大小、处理多余依赖，或需要更复杂的启动流程。接下来我们将分享一些“自己动手”的技巧和最佳实践。

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

* 在断定某个问题与自定义 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) 来托管数据库和长时间运行的服务。

[^1]: 个人访问令牌

[^2]: 禁用兼容性检查

[^3]: 使用 IpNetDriver

[^4]: 设置客户端/服务器的更新频率和超时

[^5]: 将服务器构建设置为默认目标

[^6]: 启用日志

[^7]: 不要使用检查

[^8]: 不要打包编辑器内容

[^9]: 不要打包 Slate UI（编辑器）

[^10]: 不要编译 CEF3（编辑器）

[^11]: 创建父目录

[^12]: 复制 steamclient.so 文件

[^13]: 允许执行 steam 客户端

[^14]: 在您的 Steam 发布者门户中查找
