Unity

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

✔️ 准备工作

在开始之前,请确保 创建一个 Edgegap 免费帐户 (无需信用卡)。

在你的开发机器上配置一些必需项:

安装 Unity Linux 构建支持模块
  • 使用 Unity Hub 选择选项卡 安装,访问 设置添加模块 对每个打算与 Edgegap 平台一起使用的 Unity 版本:

  • 向下滚动以选择并安装以下 Unity 模块:

    • Linux 构建支持(IL2CPP),

      • Linux 构建支持(Mono),

      • Linux 专用服务器构建支持

安装 Docker Desktop(或 Docker CLI)
安装 Edgegap 的 Unity 专用服务器快速入门插件

请参考 官方插件仓库 以获取有关安装的详细说明。

对你的服务器构建有信心吗? 跳转到 Unity高级功能 以了解更多。

⚙️ 1. 连接账户

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

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

故障排除与常见问题

!Success: 400 BAD REQUEST - POST | https://api.edgegap.com/v1/wizard/init-quick-start - {"message": "浏览器(或代理)发送了服务器无法理解的请求。"}

  • 如果你是通过复制 ZIP 文件安装或使用包含以这种方式安装的插件副本的示例项目,你需要手动安装包依赖项,包括 Newtonsoft JSON 库,参见 官方插件仓库.

  • 如果不是这种情况,请通过以下方式联系我们 社区 Discord 以获取帮助。

🔧 2. 构建游戏服务器

无论你使用的是 Windows、Mac 还是 Linux 机器,你都需要 为 Linux 运行时构建你的服务器,因为现在大多数云提供商(包括 Edgegap)都运行在 Linux 上。别担心,使用我们的插件完成此操作不需要 Linux 知识。

☑️ 验证你已安装所需的 Unity Linux 构建工具。

安装 Unity Linux 构建支持模块
  • 使用 Unity Hub 选择选项卡 安装,访问 设置添加模块 对每个打算与 Edgegap 平台一起使用的 Unity 版本:

  • 向下滚动以选择并安装以下 Unity 模块:

    • Linux 构建支持(IL2CPP),

      • Linux 构建支持(Mono),

      • Linux 专用服务器构建支持

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

高级 Unity 用户 - 可选择更改 Unity 构建设置。注意!这可能会破坏你的构建。

☑️ 可选:从 Edgegap 服务器托管菜单(在层级窗口中右键 / )将与网络代码相关的端口验证和环境引导脚本添加到你的初始服务器场景。

一旦你完成步骤 Unity,如果你的网络代码地址或端口与 Edgegap 的 应用版本端口映射 配置不匹配,端口验证脚本将记录警告。

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

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

故障排除与常见问题

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

  • 在构建服务器之前打开你的包并禁用 OpenXR。

  • OpenXR 插件仅客户端需要,并且与 Linux 服务器构建不兼容。通过将其从服务器构建中排除,你不会失去任何功能。

🐋 3. 将服务器容器化

在一个开发团队中工作意味着要共享代码。当出现问题时,你最不想听到的是“在我机器上可以运行”。游戏服务器必须能在任何机器上可靠运行,因为成功的游戏服务器将运行在全球成千上万台服务器上。

为帮助使你的服务器可靠,我们使用 Docker —— 一种虚拟化软件,确保你的所有服务器代码依赖项直到操作系统级别在任何情况下或任何地点启动服务器时都保持完全一致。

我们建议观看 “永远不要本地安装”(视频). 使用 Docker 时你不需要使用 Dockerhub。Docker ≠ Dockerhub。把 Docker 想象成一个编程引擎,而 Dockerhub 则像它的应用商店。

☑️ 现在,先点击 验证 按钮以确保你已完成 开发者工具.

安装 Docker Desktop(或 Docker CLI)

☑️ 你可以配置以下选项(或保留默认):

  • 构建路径 是指向你的服务器构建产物的相对路径,暂时保留默认即可。

  • 镜像名称 是你选择的唯一标识符,用于在发布前标记你的服务器构建。

    • 通常,这将包含你的游戏名称,例如“my-game-server”。

  • 镜像标签 是指向镜像特定版本的标识符。

    • “构建产物”一词有时用于指代你镜像的特定版本。

    • 时间戳是标记的一个好选项,例如 2024.01.30-16.23.00-UTC .

  • Dockerfile 路径 可用于自定义镜像的配方。

    • 我们建议暂时保留默认设置,你可以稍后在章节中阅读更多内容 Unity.

  • 可选的 docker 构建参数 可用于进一步指示 Docker 有关更细微的细节。

☑️ 一旦你对配置满意,点击 使用 Docker 容器化,等待进程完成并确认 Unity 控制台中没有新错误。完成此步骤将导致 在本地机器上出现新镜像。你可以在 Docker Desktop 的本地(默认)下的 Images 选项卡中验证,或在 docker CLI 中运行 docker images .

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

故障排除与常见问题

/bin/bash: docker: command not found ,或 找不到 Packages\com.edgegap.unity-servers-plugin\Editor

  • 首先,确保你已完成 开发者工具.

  • 确认你已验证你的 Edgegap 帐户,你应已收到一封带有验证链接的电子邮件。

  • 某些设置在更新 Docker Desktop 后可能已重置。尝试转到 Docker Desktop 设置 / 高级,在“选择如何配置 Docker CLI 工具的安装方式:”中选择“系统(需要密码)”。


docker build 需要恰好 1 个参数

  • 请验证你的镜像标签不包含任何空白字符(空格、制表符)。重新输入镜像标签值以确保你没有意外复制这些字符。


(HTTP 代码 400)意外 - 无效的标签格式


ERROR: failed to solve: ubuntu:22.04: failed to resolve source metadata for http://docker.io/library/ubuntu:22.04: failed to authorize: failed to fetch oauth token

  • 你位于中国吗?你的连接可能被防火长城中断。尝试运行 docker pull ubuntu:22.04 在你的命令行中手动运行(通过按 Win+R 打开命令行,然后输入 cmd 并回车)。


System.IndexOutOfRangeException: 索引超出数组范围。

  • 如果你是通过下载 ZIP 安装我们的 Unity 快速入门插件,可能你的 Unity 编辑器缓存已损坏。尝试删除插件副本并使用 git URL 或从 Unity 资源商店安装。你不再需要单独的 Newtonsoft.JSON 包,因为它已随其他来源自动包含。


我的 docker 镜像体积巨大(超过 1GB)/ 很小(低于 100MB),这样可以吗?

  • 在某些情况下这可能没问题,只要你能成功运行服务器并建立连接(见 Unity)。如果不是这种情况,请考虑检查你的构建选项,将其重置为默认值,然后逐步添加选项以查看它们如何影响构建大小。另见 Unity.


我遇到了文档中未提及的其他问题。

🧪 4. 在本地测试服务器

让我们尝试在本地(在你的机器上)部署并连接一个游戏客户端,以确保服务器镜像在我们上传和部署之前正常运行(上传和部署可能需要一些时间)。

☑️ 你可以配置以下选项(或保留默认):

  • 服务器镜像标签 来自上一步。

    • 默认使用你通过插件构建的最后一个标签。

  • 可选的 docker 运行参数 可用于暴露多个端口,或在 macOS 机器上运行你的镜像。

    • 如果需要,你可以为容器发布多个端口,只需为每个添加参数 -p {内部端口}/{协议} 例如 -p 8080/tcp -p 7770/udp 以发布并映射你的服务器端口 8080 到一个随机外部端口用于 TCP 连接,并同时将服务器端口 7777 映射到一个随机外部端口用于 UDP 连接。

    • 在你的传输或网络代码特定设置中查找服务器端口配置。

    • 如果你使用的是 ARM 架构的机器(macOS M1、M2、M3 等),你应该在可选的 docker 构建参数中看到包含此可选参数: --platform=linux/amd64 .

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

更多细节请参见 Docker Desktop / Containers,或 Docker CLI 命令 docker ps .

☑️ 现在是时候 将你的 Unity 编辑器游戏客户端连接到本地 docker 容器 以验证你的服务器镜像是否正常运行。找到你的网络代码客户端设置并输入:

  • localhost127.0.0.1 (在大多数情况下等效)代替服务器 IP,

  • 在 Docker Desktop / Containers / edgegap-server-test 中找到的随机化外部端口值。

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

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

故障排除与常见问题

我无法使用我的 Unity 编辑器游戏客户端连接到本地 docker 容器。

  • 首先,确保容器状态为 Up 且不是 Restarting 或 Exited,这些状态表示运行时异常。如果容器未运行,请通过 Docker Desktop 的 Containers 选项卡(点击你的容器)或使用 docker logs {container_id} --timestamps 通过 docker CLI 检查其日志。

  • 接下来,请验证你的服务器构建中的网络管理器端口设置与 可选的 docker 运行参数中发布的端口是否匹配。如果不匹配,尝试重置或手动更改此输入字段的值以匹配 {container} 端口与你的网络管理器设置。请在你的网络代码设置中查找你的协议。

  • 最后,确认你的 Unity 编辑器游戏客户端网络代码设置正在使用 可选的 docker 运行参数 中发布的端口(见上方截图)。


(段错误)- 已生成核心转储

  • 如果你使用的是 ARM 架构的机器(macOS M1、M2、M3 等),你应该在可选的 docker 构建参数中看到包含此可选参数: --platform=linux/amd64 。如果没有,请尝试重置该输入字段的值。


SceneId 为 9120233082191360994 未在 SceneObjects 中找到。

  • 这可能意味着你尝试加载的场景未正确包含在构建中,这是旧插件版本中的已知问题。为解决此问题,请尝试更新你的网络代码集成版本或 更新你的 Edgegap 插件.


http2: server: error reading preface from client //./pipe/docker_engine: file has already been closed


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

  • 此错误表示根 SSL 证书验证问题,是旧插件版本中的已知问题。为解决此问题,请尝试 更新你的 Edgegap 插件.

☁️ 5. 上传到 Edgegap

现在是将你的服务器上线部署的时候了!既然你的镜像可以成功承载玩家,我们就可以将其上传到 Edgegap 并开始在全球任意地点运行。在本指南中,我们将使用 Edgegap 的容器注册表 (镜像存储)。

☑️ 你可以配置以下选项(或保留默认):

  • 应用名称 在 Edgegap 上可以与镜像名称相同或自定义。

    • 我们暂时选择复制你的镜像名称。

  • 应用版本 在 Edgegap 上可以与标签相同或自定义。

    • 时间戳是应用版本名称的一个好选项,例如 2024.01.30-16.50.20-UTC .

    • 多个应用版本可以指向相同的镜像标签,例如 v1.1.0dev .

    • 了解更多关于 应用与版本 稍后。

  • 服务器镜像名称 来自步骤 Unity.

  • 服务器镜像标签 来自步骤 Unity.

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

☑️ 你将被带到我们的 仪表盘,在那里你可以配置可选设置。完成此步骤将导致 创建一个新的应用版本,并且你的 构建产物将被标记并上传到 Edgegap 的容器注册表.

☑️ 现在系统会提示你为新的应用版本定义一个端口。确保将与步骤中相同的服务器端口值设置为你的传输或网络代码特定设置中的值。 Unity 🚀 6. 部署到云端

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

故障排除与常见问题

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

  • 看起来你的镜像存储空间已在以下位置用尽 容器镜像仓库。请考虑删除未使用的构建产物(如果有的话)或优化服务器构建大小。如果使用自定义 Dockerfile 或 .dockerignore,可能会将一些不需要的文件复制到镜像中。


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

  • 你已达到我们免费套餐的限制,请考虑升级你的账户。或者,你可以通过我们的界面移除现有资源 仪表板.


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

  • 请确保你在最后一步已完成应用版本创建表单。

☑️ 现在我们将进行最后测试并

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

☑️ 选择一个应用程序和版本 从上一步部署。

☑️ 一旦准备就绪,点击 部署到云端,等待达到 部署。完成此步骤将会 新的部署正在启动 在你的 Edgegap 帐户上。

☑️ 验证控制台输出中没有新的错误。同时确保你的 部署 没有显示任何错误,并且你的 部署 未显示 100% 资源利用率(vCPU 或内存),否则新的玩家连接可能会被拒绝,或你的服务器陷入重启循环。请参阅下面的故障排除步骤以解决任何问题。

将你的 Unity 编辑器游戏客户端连接到你的云部署 。从部署的以下项输入游戏客户端连接详细信息:主机

  • URL 指向服务器的 IP,通常在 NetworkManager 组件中。 外部端口

  • 映射到 服务器的内部监听端口 ,通常在传输组件中。无法将客户端连接到服务器 -

您在 Edgegap 云上的部署的外部端口将随机选择,以便潜在的攻击者(黑客)在造成损害之前被延缓并被检测到。

☑️ 一旦您确认能够毫无问题地连接到部署并完成测试, 停止您的部署 以释放您帐户中的容量以供下次构建使用。

🙌 恭喜您在 Edgegap 上完成第一次部署!如果您想了解更多,请继续阅读。

故障排除与常见问题

请求超时。 请求超时。 , ConnectionFailed , 端口验证失败 ,或 首先,确保部署状态为 Ready,并且部署日志中没有运行时异常或错误。如果你的部署已停止,请在我们的


我的部署停止/重启并且我无法再访问它的日志。

  • 如果服务器进程因异常崩溃,我们的系统会尝试自动重启服务器。考虑 在本地测试你的服务器 以查明根本原因。

  • 我们仅在部署期间保留日志,如果你希望在部署停止后检查日志,请 集成第三方日志存储.

  • 参见 部署 以了解导致部署停止的所有原因。


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

  • 免费层部署有 60 分钟限制,请考虑升级你的帐户。

  • 所有部署在运行 24 小时后将根据我们的服务器清理策略被终止,旨在进行基础设施维护并防止在部署未正确关闭时产生意外费用。对于长期运行的服务器,请考虑使用 智能舰队.

  • 参见 部署 以了解导致部署停止的所有原因。


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

  • 一旦部署就绪,你的游戏引擎初始化便开始。此过程可能需要几秒到几分钟不等,在此期间服务器不接受玩家连接。

  • 考虑优化服务器初始化以缩短此时间。

  • 游戏客户端应以 1 秒间隔重试连接,有限次数(取决于你的初始化时长),之后应返回匹配流程。

  • 考虑添加一个加载场景,以便服务器在客户端初始化(以及在 Unreal Engine 中进行 travel)时同时执行初始化,并同步双方的状态。


我的 Meta Quest 设备抛出 HTTP 0:无法解析目标主机 .

  • 在为 Android 目标构建 Unity 应用时,你的 Internet Access 权限可能会被自动从输出的 APK 客户端构建产物中移除。

  • 重新在以下位置添加权限(需要随后重建客户端):

    • 项目设置 / OpenXR / ⚙️ Meta Quest 支持 / 强制移除 Internet 权限(取消勾选)。

    • Player 设置 / Internet Access(设置为 require)。


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

  • 默认情况下,服务器不会拒绝玩家连接。玩家认证由你的开发者负责,因为可以使用多种不同的方法和玩家认证提供商。

  • 游戏客户端可以将连接信息本地存储,以便在意外客户端崩溃时尝试重新连接。

  • 为允许玩家加入正在进行的游戏,考虑使用 深入解析会话.


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

  • 这可能不是问题,因为游戏引擎在服务器初始化期间往往会执行大量 CPU 密集型操作。如果 CPU 使用率在部署开始后 2-3 分钟内未下降,你可能需要优化服务器或增加应用版本资源。

  • 降低 tick 率可以影响 CPU 使用,因为服务器将执行更少的消息操作。

  • 如果你使用 Mirror 网络代码,你需要在 “自动启动服务器” 中选中 组件中。 ,重新构建、推送并重新部署你的服务器。

  • 如果你使用 FishNet 网络代码,你需要在你的 中启用 “在无头模式启动” ServerManager,重新构建、推送并重新部署你的服务器。

  • 在免费层中你被限制为 1.5 vCPU 和 3GB 内存(RAM)。

  • 你可以在创建新应用版本时增加分配的资源。你可以在我们的仪表盘中复制应用版本并根据需要调整这些值,无需重新构建服务器或镜像。


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

  • 这是由于超出分配的内存量造成的。考虑通过对象池、压缩或在场景中移除不必要的对象来优化内存使用。

  • 确保你的项目正在加载包含你的 组件中。 的默认场景,并且该场景已包含在 Unity 的构建设置中。

  • 在免费层中你被限制为 1.5 vCPU 和 3GB 内存(RAM)。

  • 你可以在创建新应用版本时增加分配的资源。你可以在我们的仪表盘中复制应用版本并根据需要调整这些值,无需重新构建服务器或镜像。


有时,我的服务器内存(RAM)使用会飙升到很高,这会是问题吗?

  • 只要你保持在分配的应用版本内存范围内,这不是问题。

  • 超出分配的应用版本内存量将导致 OOM kill (见上文)。


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

  • 不会,我们的平台确保分配的资源不会被其他工作室或共享基础设施上的其他服务器使用。在 Edgegap 上,没有噪声邻居问题。

👉 接下来的步骤

一旦你有了可运行的客户端/服务器设置,确保 保存你的项目副本 (使用像 git 这样的版本控制软件),以便在遇到问题时你始终可以追溯你的步骤。

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

停止部署

了解各种方法来 停止部署 一旦比赛结束并且玩家离开。

如果 Unity 服务器崩溃或内存耗尽,将自动重启。

注入变量

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

通过检查 Edgegap 变量是否设置来验证当前实例是游戏客户端还是服务器

匹配器

手动启动你的部署并粘贴 URL 和端口并不足以用于在线游戏。

仅重新构建自上次构建以来更改的资源。

考虑使用

Unity 的增量构建 以加快构建时间。 只包含服务器运行所绝对需要的内容。

在镜像中复制未使用的文件会导致镜像膨胀、更长的上传时间、更慢的缓存速度以及整体服务器启动变慢。

禁用静态合批以加快构建、上传和部署速度。

将网格压缩设置为 高 以加快构建、上传和部署。

通过

Unity 的增量构建 来跳过加载某些资源.

  • 多阶段 Docker 构建(链接)

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

)。

自定义服务器镜像 Unity我们还支持为需要更多控制其镜像(由于构建大小优化、额外依赖或需要更复杂的启动流程)的用户添加自己的 Dockerfile。你可以在步骤中可选地提供自定义 Dockerfile 的路径。我们现在将分享一些“自己动手”的技巧和最佳实践。

使用 Websockets 或 HTTPS 请求时遇到问题?

  • 如果你看到 Curl 错误 35:证书握手失败。致命错误。UnityTls 错误代码:7 不要灰心,这是包含过期根证书的旧基础(如果你不确定为什么你的某个 Dockerfile 命令抛出错误,尝试在本地调试。在问题发生之前创建一个新阶段(添加第二个)镜像的已知问题。你可以通过更新到较新的基础镜像版本(例如 ubuntu:22.04)并运行 update-ca-certificates 来修复它,在你的 Dockerfile 中添加以下内容:

始终确保您使用的是可正常工作的服务器构建。

  • 在假设问题与自定义 Dockerfile 有关之前,请确保您的 Unity 服务器构建可以启动,并且 Unity 中的构建过程没有抛出任何异常或错误。

在上传之前务必先进行本地测试。

  • 在本地测试镜像可以为您节省大量等待上传完成的时间。它也完全免费 ✨ 因为不需要任何 Edgegap 资源。

  • 在本地测试时,请确保正确设置内部端口:

确保掌握基本要点。每个 Dockerfile 都需要一些基本命令:

  • FROM {image} 是您的基础镜像,对于 Unity 项目我们通常使用长期支持的 Linux,但任何基于 Linux 的基础镜像都可以。这些通常是存放在 dockerhub 上的公共镜像。Dockerfile 参考在此处。 Dockerfile 参考在此处.

  • COPY {source} {destination} 将您的 Linux 服务器构建从主机复制到镜像内部,以便您稍后可以启动它。 Dockerfile 参考在此处.

  • USER {user} 应当跟在 useradd(ubuntu)命令 或等效命令之后,最好不要以 root 身份运行所有内容,以更安全为宜。 Dockerfile 参考在此处.

  • CMD {command} 将是最后一行,很可能会调用一个 StartServer.sh 或某种启动脚本,以确保在所有设置完成后服务器正确初始化。 Dockerfile 参考在此处.

  • 切勿使用 VOLUME - 这样您将无法在 Edgegap 上挂载任何本地存储,请改用我们的端点存储功能并使用 S3 存储桶,参见 端点存储,

  • EXPOSE 7777/UDP 不是必需的!这实际上不会使容器外部可用内部服务器端口,它只是对开发者的提示,端口需要被

    • 在本地使用以下命令测试时发布: docker run <image> -p 7777/udp ,

中映射。 将参数的声明延迟到尽可能晚的时刻。由于服务器构建时间较长,可配置性优于可组合性。

  • 将此方法应用于 Dockerfile 命令以更快地构建和上传。

  • 场景:您需要定义诸如部署阶段、版本、游戏模式、地图、每台服务器的玩家数、备份频率或类似参数。

  • 糟糕的解决方案:为每一种参数组合创建单独的镜像。您会把所有时间都花在重建镜像上,而这种方法带来的好处非常有限。

    1. 更好的解决方案——即时替换配置参数:

    2. 部署参数——在部署前提供——匹配选择器作为环境变量传入,或由您自定义的会话管理系统在部署时传入环境变量,

    3. 版本参数——在某个应用版本的所有部署间共享——部署阶段、制品标签、第三方密钥和端点等;然后

单一镜像——包含并在启动时加载所有配置选项。

  • 切勿在 Edgegap 部署上运行数据库。

  • Edgegap 部署并不适合长期运行的进程,且可能在长时间运行后被终止而不另行通知。以这种方式运行的数据库(即使是分布式的)可能会被终止并导致不可逆的数据丢失。如果您需要数据库,请考虑第三方 DBaaS。 托管集群 考虑使用我们的

遇到困难?我们在我们的 社区 Discord 中在线并乐于提供帮助。

最后更新于

这有帮助吗?