> 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/learn/pi-pei/matchmaker-in-depth.md).

# 深入了解

深入了解 Edgegap 的无代码匹配器概念，并按需自定义。

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

## ✔️ 简介

基于对战的游戏中的匹配系统通常旨在：

* **找到其他玩家** 基于诸如区域、延迟、技术水平或游戏参数等条件；
* **搜索服务器** 根据可用容量\[或延迟、区域、技术水平、地图、模式]加入；
* **启动新服务器** 如果现有服务器已满或不满足玩家条件。

玩家体验至上，定义我们的核心目标：

* 高对局填充率和社交功能整合（与好友组队游戏），
* 快速匹配且控制匹配质量（低延迟、共享偏好），
* 可靠且可预测的匹配流程并具有全球可用性。

{% hint style="success" %}
或者，让玩家 **从列表中选择一个持久的（始终在线）服务器** 带有 [服务器浏览器](/zh/learn/fu-wu-qi-liu-lan-qi.md).
{% endhint %}

**5 分钟内即可开始，并免费测试所有功能，无需信用卡。**

当你准备好使用更强大、私有（专用）的集群时即可升级。与 Edgegap 原生集成 [部署](/zh/learn/bian-pai/deployments.md) 无论你的玩家位于何处，都能提供一流的延迟表现。

{% hint style="info" %}
免费层在每次重启后可运行 3 小时。你的匹配器将在共享基础设施上运行，资源有限，适合测试。 **在公开发布后，匹配器需要 24/7 运行。**
{% endhint %}

每个匹配器都有三个核心概念：

* [#hosting-cluster](#hosting-cluster "mention") - 底层服务器基础设施，由 Edgegap 全面管理和运营。
* [#configuration](#configuration "mention") - 定义匹配器如何运行的一组规则和设置。
* 🌐 服务实例 **-** 在集群上 24/7 运行的实时匹配服务，使用配置将玩家匹配在一起并生成部署（服务器）分配。

{% hint style="success" %}
[请经常更新你的匹配器版本](#changelog) 以 **充分利用新功能和错误修复。**
{% endhint %}

## ▶️ 开始匹配

**快速开始——将我们的 SDK 入门示例添加到你的游戏中**:

* 虚幻引擎 [开发者工具](/zh/unreal-engine/developer-tools.md#integration-kit):
  * [阅读文档](https://egik.betide.studio/) 由 Betide Studios，
  * [从 Fab Marketplace 安装](https://www.fab.com/listings/ff17ad88-12a1-49cf-9a41-31695ed11e16) （个人使用免费），
  * [导入简单示例蓝图](https://blueprintue.com/blueprint/m33u1okj/) （匹配）并根据你的需要进行自定义。
* Unity [开发者工具](/zh/unity/developer-tools.md#software-development-kit):
  * [使用 Unity Package Manager 免费安装包](https://github.com/edgegap/edgegap-unity-sdk),
  * [探索我们的入门指南和完整示例](/zh/unity/pi-pei.md).

了解匹配流程，以便自定义、排查问题并优化你的游戏集成：

<figure><img src="/files/fd3fb7c43c0894a7d02e9d8845c2d962c6f58ef7" alt=""><figcaption><p>匹配流程</p></figcaption></figure>

1. [验证玩家](#authenticate) - 防止盗版副本联机，
2. [创建大厅](#create-group) - 与好友组队，并共享玩家/比赛偏好，
3. [**组成小队**](#group-up) **- 将你的大厅注册为匹配组，**
4. [**寻找匹配**](#find-match) **- 准备就绪并开始寻找对局（新的或已有的），**
   1. 分配服务器并注入票证 - 服务器会在几秒后自动分配，
5. [**连接并验证**](#connect-to-server) **- 尝试与游戏服务器建立安全连接，**
   1. 确认身份 - 服务器使用第三方令牌验证游戏客户端身份，
   2. 接受玩家或踢出玩家 - 服务器决定是否允许玩家加入。

### 身份验证

所有请求必须发送一个 `Authorization（授权）`  HTTP 头并包含您的密钥 **认证令牌：**

<pre><code>授权： <a data-footnote-ref href="#user-content-fn-1">xxxxxxxx-e458-4592-b607-c2c28afd8b62</a>
</code></pre>

{% hint style="warning" %}
**请将您的令牌保密并妥善保存！Edgegap 员工绝不会向您索要令牌。**
{% endhint %}

{% hint style="success" %}
**此令牌可以安全地包含在你的游戏客户端中，因为它不会授予 Edgegap API 访问权限。**
{% endhint %}

可以使用票证 ID 识别单个玩家，该 ID 在客户端和服务器上均可获取。可选地，使用自定义代理并通过以下方式添加自定义身份验证或限制 [#server-to-server-api](#server-to-server-api "mention") API。

### 组成小队

创建小队（party）可确保玩家与好友加入同一队伍和服务器。

{% hint style="success" %}
创建一个已标记为就绪的小队以 [#find-match](#find-match "mention") 尽快作为一个 **没有小队成员的单人玩家**.
{% endhint %}

<figure><img src="/files/2986c898e71629ecde4a8551d360c770aef98b12" alt=""><figcaption><p>小队生命周期活动图</p></figcaption></figure>

#### 大厅和小队

如果你的游戏设计需要设置由玩家控制的匹配偏好（例如角色选择、难度、地图等），请使用大厅服务。随着玩家加入和离开大厅，他们也会更新匹配组，以便稍后寻找对局。

{% hint style="success" %}
**没有时间实现大厅服务？** 引导玩家通过 Discord 或私信分享小队 ID。
{% endhint %}

<table><thead><tr><th width="390">游戏设计 - 功能 / 需求</th><th>赛前大厅</th><th>匹配组</th></tr></thead><tbody><tr><td><a data-footnote-ref href="#user-content-fn-2">邀请好友与我一起玩</a></td><td>✅</td><td>✅</td></tr><tr><td>修改我的玩家/比赛偏好</td><td>✅</td><td>❌</td></tr><tr><td>查看其他大厅成员偏好</td><td>✅</td><td>❌</td></tr><tr><td>存储和管理自定义键值数据</td><td>✅</td><td>❌</td></tr><tr><td>通知小队成员我已准备好开始游戏</td><td>❌</td><td>✅</td></tr><tr><td>显示匹配进度并寻找对局</td><td>❌</td><td>✅</td></tr><tr><td>获取玩家/小队的队伍分配</td><td>❌</td><td>✅</td></tr><tr><td>获取游戏服务器连接详情</td><td>❌</td><td>✅</td></tr></tbody></table>

我们的跨平台匹配器支持所有商业和自定义大厅服务：

<table><thead><tr><th>大厅服务（第三方）</th><th width="120" data-type="checkbox">Unreal Engine</th><th width="75" data-type="checkbox">Unity</th><th width="50" data-type="checkbox">PC</th><th width="90" data-type="checkbox">主机</th><th width="65" data-type="checkbox">VR/XR</th><th width="100" data-type="checkbox">移动端</th></tr></thead><tbody><tr><td><a href="https://dev.epicgames.com/docs/game-services/lobbies-and-sessions/lobbies/lobbies-intro">Epic Online Services 大厅</a><br>（Epic Games）</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td><a href="https://partner.steamgames.com/doc/features/multiplayer/matchmaking#friends">Steamworks 大厅</a><br>（Valve Corporation）</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td><a href="https://heroiclabs.com/docs/nakama/concepts/groups/">Nakama 小队</a><br>（Heroic Labs）</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td><a href="https://learn.microsoft.com/en-us/gaming/playfab/community/associations/groups/quickstart">Playfab 大厅</a><br>（Microsoft）</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td><a href="https://docs.braincloudservers.com/learn/key-concepts/multiplayer/lobbies/#lobby-experience">brainCloud 大厅</a><br>（bitHeads）</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td></tr><tr><td><a href="https://developer.apple.com/documentation/gamekit/connecting-players-with-their-friends-in-your-game">Gamekit 好友</a><br>（Apple）</td><td>true</td><td>true</td><td>false</td><td>false</td><td>false</td><td>true</td></tr><tr><td>自定义大厅<br>（你的公司）</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td><td>true</td></tr></tbody></table>

大厅所有者（发送邀请的玩家）也必须创建匹配组。

**将你小队的 ID 存储在共享大厅数据中**，这样其他大厅成员就能轻松找到并加入与第三方大厅关联的匹配组。被邀请加入该小队的玩家使用小队 ID 来 **创建自己的成员资格（加入）**，并且 **安全存储他们的** [**匹配属性**](#matchmaking-rules)**.**

{% hint style="warning" %}
**一旦小队开始匹配，就无法再加入。** [#abandon-queue](#abandon-queue "mention") 并创建一个新的。
{% endhint %}

#### 延迟优化

如果 [#configuration](#configuration "mention") 包含 [`延迟` 规则](#rule-example-elo_rating) 所有小队成员发送他们的 [Ping 信标](/zh/learn/bian-pai/ping-beacons.md) 测量值到 **防止将来自远距离地区的玩家匹配在一起** 或将延迟高很多/低很多的玩家匹配在一起。

{% code title="游戏客户端延迟测量示例（毫秒）" %}

```json
{
  "芝加哥": 224.4,
  "法兰克福": 23.2,
  "东京": 167.4
}
```

{% endcode %}

#### **放弃队列**

小队所有者可以删除小队，系统会自动删除所有成员资格。在匹配开始后删除小队将取消所有成员资格，并在稍后将其删除。

小队成员（除所有者外）可在以下时间之前随时删除自己的成员资格（离开小队） [#find-match](#find-match "mention")。之后删除成员资格将取消整个小队的匹配。

{% hint style="info" %}
一旦匹配被取消，成员将 [自动从匹配中移除](#matchmaking-profiles) 并通过成员资格通知 `状态：CANCELLED`  ，并在他们下一次状态轮询响应中获知。
{% endhint %}

一旦取消，如果小队希望重新开始匹配，小队所有者必须重新创建小队，将新的小队 ID 分享给成员，并让他们重新创建成员资格。

**一旦找到对局，小队就无法删除** (`409 冲突`），并将 [自动移除](#connect-to-server)。你的服务器应允许玩家有一段时间（例如 60 秒）进行连接，然后再假定玩家已放弃。

如果你的服务器将某位玩家标记为已放弃，你可以：

* 用 AI 角色替换离开的玩家，以便立即开始对局，
* 或者创建一个 [补位](#backfill-match) 来寻找新玩家替代离开的玩家，
* 或者如果你的游戏设计允许可变玩家人数，则不替换离开的玩家继续进行。

### 寻找匹配

要开始寻找对局，所有成员和所有者都必须将自己标记为就绪。

{% hint style="success" %}
为了让小队所有者 **立即开始匹配，请在创建时将成员资格标记为就绪**。一旦所有者将自己标记为就绪，匹配就会开始，因为所有人都已就绪。
{% endhint %}

{% hint style="info" %}
为了获得最佳体验， **请通过游戏内 UI 向玩家提供状态更新**.
{% endhint %}

**所有玩家必须定期轮询自己的成员资格** （建议 3–5 秒），以检测匹配何时开始，并通过游戏内 UI 传达匹配进度。

玩家应 **持久保存他们的成员资格和小队 ID**，以便在游戏客户端崩溃时，他们可以重启游戏并在不丢失匹配进度的情况下继续。

一旦我们找到足够的玩家，并按照你的 [#matchmaking-rules](#matchmaking-rules "mention")，玩家将在其成员资格响应中收到通知，显示 `状态：TEAM_FOUND`.

在此阶段删除成员资格将导致所有小队成员资格被取消，并使所有其他已分配到同一队伍的小队返回到 `状态：SEARCHING` .

队伍继续使用其小队之间的重叠值与其他队伍进行匹配（或者在以下情况下使用平均值 `数值差异` ），直到组装出足够的队伍。成员资格会通过响应  `状态：MATCH_FOUND` ，这意味着你的 [部署正在启动](https://docs.edgegap.com/zh/learn/pi-pei/pages/5e7e2169ca3822647d4607dfc1d3487ebcc0836c#id-1.-start-a-deployment).

**匹配器旨在最大化对局填充率，并且不会进入 `MATCH_FOUND` ，直到以下任一条件满足：**

1. 足够的队伍已按配置的最大队伍人数匹配，
2. 或者如果 [#rule-expansion](#rule-expansion "mention") 已定义且达到扩展时间，并且足够的队伍已按配置的最小队伍人数匹配，
3. 或者已达到配置的票证过期时间，并且足够的队伍已按配置的最小队伍人数匹配。

如果在配置的票证过期前这两种情况都未成功，小队和票证将被取消。

{% hint style="info" %}
在测试期间或玩家位于较不热门地区时遇到较长排队时间？请设置更短的票证过期时间（例如 30 秒），并在过期时在客户端重新创建小队（或票证）。
{% endhint %}

每当小队（或玩家）被匹配到某个队伍时，票证过期时间都会自动重置。

{% hint style="success" %}
存储 `team_id`  和 `match_id` 在你的游戏后端中，以便在游戏内显示队伍成员信息。
{% endhint %}

{% hint style="info" %}
每位玩家都会获得一个 **唯一的票证 ID，可用于** [#authenticate](#authenticate "mention") **与游戏服务器进行**
{% endhint %}

如果玩家已完成匹配并分配到游戏服务器，其票证会自动删除。在以下之后放弃队列的玩家 `状态：HOST_ASSIGNED`  可以替换为 [补位](#backfill-match).

一旦玩家收到 `状态：HOST_ASSIGNED`  他们就会继续进行 [#connect-to-server](#connect-to-server "mention").

### 连接到服务器

在找到匹配后几秒，成员资格将继续进入 `状态：HOST_ASSIGNED`  这表明你的 [部署现已就绪，游戏服务器正在初始化](https://docs.edgegap.com/zh/learn/pi-pei/pages/5e7e2169ca3822647d4607dfc1d3487ebcc0836c#id-3.-deployment-ready).

每位玩家读取其 `ticket_id`  和  `分配`  并尝试使用以下方式连接 [**FQDN**](#user-content-fn-3)[^3] **（部署 URL）** 以及 **外部端口**。此时你的游戏服务器可能仍在初始化，因此 **玩家必须多次重试连接**，直到超过你通常的服务器初始化时间：

{% tabs %}
{% tab title="Unreal Engine" %}
为了 **从 PIE（编辑器）连接** 在开发和测试期间，按波浪号键 `~`  并输入 `open {URL}:{port}`  并等待编辑器加载地图。

为了 **从游戏客户端构建连接** （在正式生产环境中）尝试

* Unreal Engine [⚡ 集成套件](https://docs.edgegap.com/learn/unreal-engine-games/developer-tools#integration-kit):
  * [从 Fab Marketplace 安装](https://www.fab.com/listings/ff17ad88-12a1-49cf-9a41-31695ed11e16) （个人使用免费），
  * [导入简单示例蓝图](https://blueprintue.com/blueprint/m33u1okj/) 并根据你的需要进行自定义。

{% hint style="success" %}
如果连接失败或出现黑屏，请查阅我们的 [故障排除指南](/zh/unreal-engine.md#troubleshooting-and-faq).
{% endhint %}
{% endtab %}

{% tab title="Unity" %}
为了 **连接你的 Unity 编辑器** 或 **游戏客户端** 到你的云部署，请输入：

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

{% hint style="success" %}
如果连接超时或遇到其他问题，请查阅我们的 [故障排除指南](/zh/unity.md#troubleshooting-and-faq-4).
{% endhint %}
{% endtab %}
{% endtabs %}

{% hint style="info" %}
我们不会要求玩家确认匹配，因为我们的目标是尽可能缩短进入游戏的时间、提高匹配填充率，并尽量减少排队逃避和匹配取消。
{% endhint %}

游戏客户端应 **在游戏重启之间持久保存其分配 ID**，以便在游戏客户端崩溃时能够检索连接详情并尝试重新连接。

### 补位对局

可选地，某些游戏可能有特殊的匹配需求，例如：

* 允许新玩家加入进行中的游戏（好友或“randoms”），
* 在服务器启动后替换中途离开的玩家（离开者），以避免重新开始对局，
* 允许观众加入并观看锦标赛或好友的比赛（电子竞技），
* 将玩家集中到更大的服务器中，以提供更多社交互动（MMO）。

回填是一种 **由服务器持有的票据，表示当前连接到服务器的玩家。** 这可确保新加入的玩家在与当前玩家匹配时遵守你的匹配规则。

{% hint style="warning" %}
[深入了解](/zh/learn/pi-pei/matchmaker-in-depth.md#backfill-match) 用于替换 Seat/Match 会话。匹配器仅支持 Default 会话。
{% endhint %}

<figure><img src="/files/b2aa022802913682f9fad04145e9161440cc6e17" alt=""><figcaption><p>回填场景可视化</p></figcaption></figure>

{% hint style="success" %}
**回填会忽略** `player_count`  **规则，并且始终精确匹配一个组**. `backfill_group_size`  使用轮询策略控制队伍容量，以受控且均匀的方式补满队伍。
{% endhint %}

**完成一次成功回填的步骤如下：**

1. 服务器为每个缺少玩家的队伍创建一个回填，使用以下值：
   * 真实 `分配`  从以下来源获取的数据 [部署](/zh/learn/bian-pai/deployments.md#injected-environment-variables) （部署）。
   * 当前已连接玩家的 `票据`:
     * 来自 [深入了解](/zh/learn/pi-pei/matchmaker-in-depth.md#injected-variables) （匹配器），之前回填的 `assigned_ticket` 响应，或经过修改以匹配特定玩家的模拟数据，
     * 替换 `backfill_group_size`  将值替换为可能的组大小 直至可用容量[^4],
2. 游戏客户端创建新的票据（成员资格）并包含 `backfill_group_size`  值：
   * `"1"`  如果玩家单独进行匹配。
   * [`"2"`  如果玩家属于一个总人数为 2x 的匹配组](#user-content-fn-5)[^5].
   * `"新建",`  如果玩家除了加入进行中的游戏外，还启用了开始新游戏。
3. 游戏客户端随后 [深入了解](/zh/learn/pi-pei/matchmaker-in-depth.md#find-match) 并将玩家与匹配到的回填进行配对。
4. 如果回填后的组未能完全填满队伍，服务器可以使用新回填玩家的票据重复此过程，以添加更多玩家并达到所需的队伍人数。

{% hint style="success" %}
回填会忽略队伍大小规则，并且始终让 1 个回填与 1 个组匹配。 **若只与回填匹配并禁用与队列中其他玩家的匹配，请设置 `min_team_size: 999999` .**
{% endhint %}

<details>

<summary>🥛 回填示例（回填展示）</summary>

```json
{
  "profile": "backfill-example",
  "属性": {
    "assignment": {
      "request_id": "cd28e6c66554",
      "fqdn": "cd28e6c66554.pr.edgegap.net",
      "public_ip": "192.168.2.14",
      "ports": {
        "game": {
          "internal": 7777,
          "external": 56890,
          "link": "cd28e6c66554.pr.edgegap.net:56890",
          "protocol": "UDP"
        },
        "web": {
          "internal": 22,
          "external": 57440,
          "link": "cd28e6c66554.pr.edgegap.net:57440",
          "protocol": "TCP"
        },
        "server": {
          "internal": 80,
          "external": 50110,
          "link": "cd28e6c66554.pr.edgegap.net:50110",
          "protocol": "TCP"
        }
      },
      "location": {
        "city": "蒙特利尔",
        "country": "加拿大",
        "continent": "北美洲",
        "administrative_division": "魁北克",
        "timezone": "America/Toronto"
      }
    }
  },
  "tickets": {
    "c3d057h5h6f7j889fk43": {
      "player_ip": "174.25.48.238",
      "属性": {
        "信标": {
          "纽约": 12.2,
          "洛杉矶": 45.3,
          "巴黎": 78.3
        },
        "backfill_group_size": [
          "2",
          "1"
        ]
      },
      "group_id": "192bb97e-7fd6-4d86-8ce4-61c53c9fef16",
      "id": "c3d057h5h6f7j889fk43",
      "created_at": "2024-08-20T13:38:05.251393+00:00"
    },
    "cqg0bg9583s738h9dkf6": {
      "player_ip": "217.34.85.142",
      "属性": {
        "信标": {
          "纽约": 21.0,
          "洛杉矶": 30.2,
          "巴黎": 101.1
        },
        "backfill_group_size": [
          "2",
          "1"
        ]
      },
      "group_id": "aea7df3c-d391-4ea3-a3ec-dded422fe7c8",
      "id": "cqg0bg9583s738h9dkf6",
      "created_at": "2024-08-20T13:38:05.251393+00:00"
    }
  },
  "assigned_ticket": null
}
```

</details>

<details>

<summary>🥛 回填分配示例（回填展示）</summary>

```json
{
  "profile": "backfill-example",
  "属性": {
    "assignment": {
      "request_id": "cd28e6c66554",
      "fqdn": "cd28e6c66554.pr.edgegap.net",
      "public_ip": "192.168.2.14",
      "ports": {
        "game": {
          "internal": 7777,
          "external": 56890,
          "link": "cd28e6c66554.pr.edgegap.net:56890",
          "protocol": "UDP"
        },
        "web": {
          "internal": 22,
          "external": 57440,
          "link": "cd28e6c66554.pr.edgegap.net:57440",
          "protocol": "TCP"
        },
        "server": {
          "internal": 80,
          "external": 50110,
          "link": "cd28e6c66554.pr.edgegap.net:50110",
          "protocol": "TCP"
        }
      },
      "location": {
        "city": "蒙特利尔",
        "country": "加拿大",
        "continent": "北美洲",
        "administrative_division": "魁北克",
        "timezone": "America/Toronto"
      }
    }
  },
  "tickets": {
    "c3d057h5h6f7j889fk43": {
      "player_ip": "174.25.48.238",
      "属性": {
        "信标": {
          "纽约": 12.2,
          "洛杉矶": 45.3,
          "巴黎": 78.3
        },
        "backfill_group_size": [
          "2",
          "1"
        ]
      },
      "group_id": "192bb97e-7fd6-4d86-8ce4-61c53c9fef16",
      "id": "c3d057h5h6f7j889fk43",
      "created_at": "2024-08-20T13:38:05.251393+00:00"
    },
    "cqg0bg9583s738h9dkf6": {
      "player_ip": "217.34.85.142",
      "属性": {
        "信标": {
          "纽约": 21.0,
          "洛杉矶": 30.2,
          "巴黎": 101.1
        },
        "backfill_group_size": [
          "2",
          "1"
        ]
      },
      "group_id": "aea7df3c-d391-4ea3-a3ec-dded422fe7c8",
      "id": "cqg0bg9583s738h9dkf6",
      "created_at": "2024-08-20T13:38:05.251393+00:00"
    }
  },
  "assigned_ticket": {
    "profile": "backfill-example",
    "player_ip": "244.13.201.244",
    "属性": {
      "信标": {
        "纽约": 30.2,
        "洛杉矶": 10.5,
        "巴黎": 123.9
      },
      "backfill_group_size": [
        "新建",
        "1"
      ]
    },
    "id": "cqg0bg550h7uujd77khg",
    "group_id": "e0cf41c0-f88f-456e-a032-03b1d6821a9a",
    "created_at": "2024-08-20T13:38:08.251393+00:00",
    "status": "HOST_ASSIGNED"
  }
}
```

</details>

{% hint style="info" %}
请参见 [Mirror 座位管理](https://docs.edgegap.com/docs/sample-projects/mirror-on-edgegap#bonus-seat-sessions-management) 和 [FishNet 座位管理](https://docs.edgegap.com/docs/sample-projects/fishnet-on-edgegap#bonus-seat-sessions-management) 的缓存错误，适用于 **玩家连接监控**.
{% endhint %}

一旦游戏服务器初始化完成， **你的服务器应**:

* **为每位新玩家启动弃权计时器。** 我们建议使用加载场景/关卡向已连接玩家显示加载进度——可以是完整的 3D 场景、类似大厅的社交 UI，或带进度条的加载界面。
* **持续跟踪新玩家连接或现有玩家随时间离开**:
  1. 新玩家必须向服务器声明票证 ID，以进行身份验证并将其连接映射到匹配器 [#injected-variables](#injected-variables "mention") 或 `assigned_ticket` （如果进行了补位）。
  2. 在服务器生命周期内，为未使用的玩家容量（离开者）创建新的补位。
  3. 续订已过期的补位，这些补位会在以下时间后被删除 `ticket_expiration_period`.
* **清理（删除）任何剩余的补位** 一旦 [/pages/5e7e2169ca3822647d4607dfc1d3487ebcc0836c#id-5.-deployment-stopped](https://docs.edgegap.com/zh/learn/pi-pei/pages/5e7e2169ca3822647d4607dfc1d3487ebcc0836c#id-5.-deployment-stopped "mention"):
  * Unity - [`OnApplicationQuit`](https://docs.unity3d.com/6000.0/Documentation/ScriptReference/MonoBehaviour.OnApplicationQuit.html) 回调或自定义游戏结束回调，
  * Unreal Engine - [`OnWorldDestroyed`](https://forums.unrealengine.com/t/call-function-before-quit-game/344954/2) , [`PreExit`](https://forums.unrealengine.com/t/event-on-close/298087/2) ，或自定义游戏结束回调。

{% hint style="info" %}
一旦就绪，部署会被分配一个 URL（ [服务器状态可能会丢失](https://learn.microsoft.com/en-us/dotnet/api/system.environment.getenvironmentvariable?view=net-8.0) 注入的变量（Injected Variables） [游戏服务器通常需要额外信息，例如服务器 IP、内部端口值等。注入只读环境变量是传递参数的一种可靠且与云无关的方式。](https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Core/GenericPlatform/FGenericPlatformMisc/GetEnvironmentVariable) 获取变量值。
{% endhint %}

只要提供有效的服务器分配和至少一个票证，任何配置都可用于补位。请参见 [匹配](/zh/learn/pi-pei.md#backfill-showcase) 以查看最小示例。

## ⚙️ 配置

匹配器 API 由你在创建新的（或快速重启的）匹配器时指定的 JSON 配置生成。你可以指定任意数量的配置文件，并设置不同的规则和扩展：

{% hint style="success" %}
请参见 [匹配](/zh/learn/pi-pei.md) 获取我们的 SDK 和详细示例场景。
{% endhint %}

<details>

<summary>🍀 简单示例（最小推荐配置）</summary>

<pre class="language-json"><code class="lang-json">{
  "版本": "3.2.5",
  "检查": true,
  "最大部署重试次数": 3,
  "配置文件": {
    "simple-example": {
      "ticket_expiration_period": "5m",
      "票证移除时长": "1m",
      "组不活跃移除时长": "5m",
      "应用": {
        "name": "<a data-footnote-ref href="#user-content-fn-6">my-game-server</a>",
        "version": "<a data-footnote-ref href="#user-content-fn-7">2024.01.30-16.23.00-UTC</a>"
      },
      "规则": {
        "初始": {
          "匹配大小": {
            "type": "player_count",
            "属性": {
              "team_count": 1,
              "min_team_size": 2,
              "max_team_size": 2
            }
          },
          "信标": {
            "type": "latencies",
            "属性": {
              "difference": 100,
              "max_latency": 200
            }
          }
        },
        "expansions": {}
      }
    }
  }
}
</code></pre>

</details>

<details>

<summary>🏁 高级示例（完整示例配置）</summary>

```json
{
  "version": "3.2.5",
  "inspect": true,
  "max_deployment_retry_count": 3,
  "allowed_cors_origins": [
    "https://*.my-game-server.com"
  ],
  "profiles": {
    "advanced-example": {
      "ticket_expiration_period": "5m",
      "ticket_removal_period": "1m",
      "group_inactivity_removal_period": "5m"
      "application": {
        "name": "my-game-server",
        "version": "2024.01.30-16.23.00-UTC"
      },
      "rules": {
        "initial": {
          "match_size": {
            "type": "player_count",
            "attributes": {
              "team_count": 1,
              "min_team_size": 4,
              "max_team_size": 4
            }
          },
          "beacons": {
            "type": "latencies",
            "attributes": {
              "difference": 125,
              "max_latency": 125
            }
          },
          "elo_rating": {
            "type": "number_difference",
            "attributes": {
              "max_difference": 50
            }
          },
          "selected_game_mode": {
            "type": "string_equality"
          },
          "selected_map": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          },
          "backfill_group_size": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          }
        },
        "expansions": {
          "30": {
            "elo_rating": {
              "max_difference": 150
            },
            "beacons": {
              "difference": 125,
              "max_latency": 250
            }
          },
          "60": {
            "elo_rating": {
              "max_difference": 200
            }
          },
          "180": {
            "match_size": {
              "team_count": 1,
              "min_team_size": 1,
              "max_team_size": 4
            },
            "beacons": {
              "difference": 99999,
              "max_latency": 99999
            }
          }
        }
      }
    }
  }
}
```

</details>

<details>

<summary><span data-gb-custom-inline data-tag="emoji" data-code="1f95b">🥛</span> 回填配置示例</summary>

```json
{
  "version": "3.2.5",
  "inspect": true,
  "max_deployment_retry_count": 3,
  "profiles": {
    "backfill-example": {
      "ticket_expiration_period": "30s",
      "ticket_removal_period": "1m",
      "group_inactivity_removal_period": "5m",
      "application": {
        "name": "my-game-server",
        "version": "2024.01.30-16.23.00-UTC"
      },
      "rules": {
        "initial": {
          "match_size": {
            "type": "player_count",
            "attributes": {
              "team_count": 1,
              "min_team_size": 4,
              "max_team_size": 4
            }
          },
          "beacons": {
            "type": "latencies",
            "attributes": {
              "difference": 100,
              "max_latency": 200
            }
          },
          "backfill_group_size": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          }
        },
        "expansions": {}
      }
    }
  }
}
```

</details>

<details>

<summary>⚔️ 竞技游戏示例</summary>

```json
{
  "version": "3.2.5",
  "inspect": true,
  "max_deployment_retry_count": 3,
  "profiles": {
    "casual-example": {
      "ticket_expiration_period": "5m",
      "ticket_removal_period": "1m",
      "group_inactivity_removal_period": "5m",
      "application": {
        "name": "my-game-server",
        "version": "2024.01.30-16.23.00-UTC"
      },
      "rules": {
        "initial": {
          "match_size": {
            "type": "player_count",
            "attributes": {
              "team_count": 2,
              "min_team_size": 5,
              "max_team_size": 5
            }
          },
          "beacons": {
            "type": "latencies",
            "attributes": {
              "difference": 125,
              "max_latency": 150
            }
          },
          "selected_maps": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          },
          "backfill_group_size": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          }
        },
        "expansions": {
          "30": {
            "beacons": {
              "difference": 125,
              "max_latency": 250
            }
          },
          "180": {
            "beacons": {
              "difference": 99999,
              "max_latency": 99999
            }
          }
        }
      }
    },
    "competitive-example": {
      "ticket_expiration_period": "5m",
      "ticket_removal_period": "1m",
      "group_inactivity_removal_period": "5m"
      "application": {
        "name": "my-game-server",
        "version": "2024.01.30-16.23.00-UTC"
      },
      "rules": {
        "initial": {
          "match_size": {
            "type": "player_count",
            "attributes": {
              "team_count": 2,
              "min_team_size": 5,
              "max_team_size": 5
            }
          },
          "beacons": {
            "type": "latencies",
            "attributes": {
              "difference": 125,
              "max_latency": 150
            }
          },
          "versus_ranks": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          }
        },
        "expansions": {
          "120": {
            "beacons": {
              "difference": 125,
              "max_latency": 250
            }
          }
        }
      }
    },
    "challenger-example": {
      "ticket_expiration_period": "5m",
      "ticket_removal_period": "1m",
      "group_inactivity_removal_period": "5m"
      "application": {
        "name": "my-game-server",
        "version": "2024.01.30-16.23.00-UTC"
      },
      "rules": {
        "initial": {
          "match_size": {
            "type": "player_count",
            "attributes": {
              "team_count": 2,
              "min_team_size": 5,
              "max_team_size": 5
            }
          },
          "beacons": {
            "type": "latencies",
            "attributes": {
              "difference": 125,
              "max_latency": 150
            }
          },
          "elo_rating": {
            "type": "number_difference",
            "attributes": {
              "max_difference": 50
            }
          }
        },
        "expansions": {
          "120": {
            "beacons": {
              "difference": 125,
              "max_latency": 250
            }
          }
        }
      }
    }
  }
}
```

</details>

<details>

<summary>🤝 合作游戏示例</summary>

```json
{
  "版本": "3.2.5",
  "检查": true,
  "最大部署重试次数": 3,
  "配置文件": {
    "cooperative-example": {
      "票证过期时长": "3m",
      "票证移除时长": "1m",
      "组不活跃移除时长": "5m",
      "应用": {
        "名称": "my-game-server",
        "版本": "2024.01.30-16.23.00-UTC"
      },
      "规则": {
        "初始": {
          "匹配大小": {
            "type": "player_count",
            "属性": {
              "team_count": 1,
              "min_team_size": 4,
              "max_team_size": 4
            }
          },
          "信标": {
            "type": "latencies",
            "属性": {
              "差值": 125,
              "最大延迟": 150
            }
          },
          "selected_difficulty": {
            "type": "string_equality"
          },
          "selected_map": {
            "类型": "交集",
            "属性": {
              "重叠": 1
            }
          },
          "player_level": {
            "type": "number_difference",
            "属性": {
              "max_difference": 10
            }
          },
          "回填组大小": {
            "类型": "交集",
            "属性": {
              "重叠": 1
            }
          },
          "审核标志": {
            "类型": "交集",
            "属性": {
              "重叠": 1
            }
          }
        },
        "扩展": {
          "30": {
            "信标": {
              "差值": 125,
              "最大延迟": 250
            },
            "player_level": {
              "max_difference": 20
            }
          },
          "60": {
            "匹配大小": {
              "team_count": 1,
              "min_team_size": 2,
              "max_team_size": 4
            }
          },
          "150": {
            "匹配大小": {
              "team_count": 1,
              "min_team_size": 1,
              "max_team_size": 4
            }
          }
        }
      }
    }
  }
}
```

</details>

<details>

<summary>🎈 社交游戏示例</summary>

```json
{
  "版本": "3.2.5",
  "检查": true,
  "最大部署重试次数": 3,
  "配置文件": {
    "社交示例": {
      "票证过期时长": "3m",
      "票证移除时长": "1m",
      "组不活跃移除时长": "5m",
      "应用": {
        "名称": "my-game-server",
        "版本": "2024.01.30-16.23.00-UTC"
      },
      "规则": {
        "初始": {
          "匹配大小": {
            "属性": {
              "队伍数量": 1,
              "最小队伍大小": 50,
              "最大队伍大小": 50
            },
            "类型": "玩家数量"
          },
          "信标": {
            "属性": {
              "差值": 125,
              "最大延迟": 150
            },
            "类型": "延迟"
          },
          "所选模式": {
            "类型": "交集",
            "属性": {
              "重叠": 1
            }
          },
          "回填组大小": {
            "类型": "交集",
            "属性": {
              "重叠": 1
            }
          },
          "审核标志": {
            "类型": "交集",
            "属性": {
              "重叠": 1
            }
          }
        },
        "扩展": {
          "15": {
            "信标": {
              "差值": 125,
              "最大延迟": 250
            },
            "匹配大小": {
              "队伍数量": 1,
              "最小队伍大小": 20,
              "最大队伍大小": 50
            }
          },
          "30": {
            "匹配大小": {
              "队伍数量": 1,
              "最小队伍大小": 10,
              "最大队伍大小": 50
            }
          },
          "150": {
            "匹配大小": {
              "队伍数量": 1,
              "最小队伍大小": 1,
              "最大队伍大小": 50
            }
          }
        }
      }
    }
  }
}
```

</details>

{% hint style="warning" %}
编辑正在运行的匹配器将 **触发快速重新加载**，删除所有票证并导致短暂停机。
{% endhint %}

<details>

<summary><code>应用配置对于配置文件 XYZ 无效。</code></summary>

* 我们找不到您的 [应用与版本](/zh/learn/bian-pai/application-and-versions.md)，请验证 `应用`  值。

</details>

<details>

<summary><code>标签为 '2024.01.30-16.23.00-UTC' 的 Docker 镜像未被缓存。</code></summary>

[**🌟 升级到按需付费等级**](https://app.edgegap.com/user-settings?tab=memberships) **以解锁** [**具有缓存的即时部署**](https://docs.edgegap.com/zh/learn/pi-pei/pages/5e7e2169ca3822647d4607dfc1d3487ebcc0836c#id-1.-start-a-deployment)**.**

* 4GB 以上未缓存的镜像可能需要更长时间部署，导致 [/pages/5e7e2169ca3822647d4607dfc1d3487ebcc0836c#id-4.-deployment-error](https://docs.edgegap.com/zh/learn/pi-pei/pages/5e7e2169ca3822647d4607dfc1d3487ebcc0836c#id-4.-deployment-error "mention")。请考虑优化您的服务器镜像大小（[虚幻引擎](/zh/unreal-engine.md#optimize-server-build-size) / [Unity](/zh/unity.md#optimize-server-build-size)).
* 您仍然可以继续，但我们建议测试您的部署时间。

</details>

### 配置文件（队列） <a href="#matchmaking-profiles" id="matchmaking-profiles"></a>

配置文件表示彼此完全独立的匹配队列，但共享同一匹配器版本。你可以 **为每个匹配器配置任意数量的配置文件。** 将玩家基础拆分到多个配置文件中，可能会导致玩家排队时间更长。

每个匹配器配置文件都使用一个 [应用版本](/zh/learn/bian-pai/application-and-versions.md) 作为启动新部署（服务器）的模板。

{% hint style="success" %}
某些游戏模式可能需要更多 vCPU / RAM，尤其是在支持更多玩家时。每个 **匹配器可能包含多个配置文件**，每个都链接到一个资源已调整的应用版本。
{% endhint %}

### 规则 <a href="#matchmaking-rules" id="matchmaking-rules"></a>

每位玩家和每个小队都会加入匹配队列，并使用  `初始` 规则首先进行匹配。

路径为以下位置的配置文件中的每个条目 `.rules.initial` 都表示一条规则，其中：

* **key** 是一个字符串值，用于按你喜欢的方式命名该规则；例如 `match_size` ，而
* **value** 是一个对象，用于定义该规则的类型和属性，并遵循我们的标准规则集。

{% hint style="info" %}
所有规则必须同时满足，才能启动主机分配并开始或查找部署。
{% endhint %}

**运算符（规则类型）**

**`player_count`** 是一条特殊规则，用于定义启动分配需要匹配多少玩家。

{% hint style="warning" %}
规则 `player_count`  **是必需的，并且只能定义一次** 在你的初始配置规则中。
{% endhint %}

匹配器始终致力于最大化对局填充率，直到指定的 `max_team_size` :

1. 如果达到最大队伍人数，对局将立即生成，
2. 否则，玩家会在队列中等待以补满对局，直到 [扩展](#rule-expansion) （或过期）即将到来，
3. 在即将 [扩展](#rule-expansion) （或过期）之前，如果可以形成部分匹配（≥ 最小且 < 最大队伍人数），则该对局将由处于同一扩展阶段的所有玩家组成（假设其他规则通过）。

{% hint style="success" %}
对于合作、自由混战或非对称队伍人数的游戏模式，请设置你的 `"team_count": 1` .
{% endhint %}

队伍数量可以配置为为竞技游戏组成多个平衡队伍：

* **小队属性按平均值/重叠值计算** 基于小队的 **玩家属性，**
* **队伍属性按平均值/重叠值计算** 基于队伍的 **小队属性。**

假设固定队伍人数为 4 名玩家：

<figure><img src="/files/6c94344ccea1ee9cc5f63b44904bbc571db195da" alt=""><figcaption><p>匹配示例场景</p></figcaption></figure>

{% hint style="info" %}
**小队在队伍中匹配时不会超载，** 前提是队伍有足够容量容纳整个小队。
{% endhint %}

**`string_equality`** 匹配字符串值完全相同的玩家。

<details>

<summary>规则示例： <code>selected_game_mode</code></summary>

`selected_game_mode`  规则将区分大小写地匹配玩家：

:white\_check\_mark: Alice + Bob + Dave 可以匹配，

:x: Alice + Erin，或 Charlie + Frank 永远不会匹配。

| "自由混战" | "夺旗"    | "夺旗"  |
| ------ | ------- | ----- |
| Alice  | Erin    | Frank |
| Bob    | Charlie |       |
| Dave   |         |       |

</details>

**`数值差异`** 匹配彼此数值绝对差在范围内的玩家。

<details>

<summary>规则示例： <code>elo_rating</code></summary>

`elo_rating`  上述规则，配合 `"max_difference": 50` 初始时：

:white\_check\_mark: Alice + Bob 可以匹配，或 Bob + Charlie 可以匹配，

:x: Alice + Bob + Charlie 永远不会匹配。

<figure><img src="/files/f41fb86b188714dee6fbad698fe0999c886ffd4c" alt=""><figcaption></figcaption></figure>

</details>

**`延迟`** 是一条特殊规则，用于优化玩家匹配的 ping：

* 通过移除延迟高（超过阈值）的区域来降低客户端-服务器延迟，
* 通过将延迟相近（差值低于指定值）的玩家分组来提高匹配公平性。

<details>

<summary>规则示例： <code>信标</code></summary>

`信标` 已配置为以下内容的规则 `"difference": 100, "max_latency": 200`  将匹配：

:white\_check\_mark: Alice 和 Bob 可能匹配：

* 东京被丢弃（>200 毫秒），
* 芝加哥的延迟绝对差在 100 毫秒以内。

<table><thead><tr><th width="180">信标城市</th><th width="80">匹配</th><th width="132">abs(A - B) [毫秒]</th><th width="164">Alice [毫秒]</th><th width="164">Bob [毫秒]</th></tr></thead><tbody><tr><td>芝加哥</td><td><span data-gb-custom-inline data-tag="emoji" data-code="2705">✅</span></td><td>75.0</td><td>12.3</td><td>87.3</td></tr><tr><td>洛杉矶</td><td><span data-gb-custom-inline data-tag="emoji" data-code="274c">❌</span></td><td><a data-footnote-ref href="#user-content-fn-8">113.2</a> <span data-gb-custom-inline data-tag="emoji" data-code="274c">❌</span></td><td>145.6</td><td>32.4</td></tr><tr><td><del>东京</del></td><td>不适用</td><td>不适用</td><td><a data-footnote-ref href="#user-content-fn-9"><del>233.2</del></a> <span data-gb-custom-inline data-tag="emoji" data-code="274c">❌</span></td><td><a data-footnote-ref href="#user-content-fn-9"><del>253.2</del></a> <span data-gb-custom-inline data-tag="emoji" data-code="274c">❌</span></td></tr></tbody></table>

:x: Alice 和 Charlie 永远不会匹配：

* 没有任何信标对两位玩家都具有 < 200 毫秒的延迟，
* Alice 住在北美 - 伊利诺伊州，
* Charlie 住在亚洲 - 日本。

<table><thead><tr><th width="180">信标城市</th><th width="80">匹配</th><th width="132">abs(A - B) [毫秒]</th><th width="164">Alice [毫秒]</th><th width="164">Charlie [毫秒]</th></tr></thead><tbody><tr><td><del>芝加哥</del></td><td>不适用</td><td>不适用</td><td>12.3</td><td><a data-footnote-ref href="#user-content-fn-9"><del>215.6</del></a> <span data-gb-custom-inline data-tag="emoji" data-code="274c">❌</span></td></tr><tr><td><del>洛杉矶</del></td><td>不适用</td><td>不适用</td><td>145.6</td><td><a data-footnote-ref href="#user-content-fn-9"><del>238.3</del></a> <span data-gb-custom-inline data-tag="emoji" data-code="274c">❌</span></td></tr><tr><td><del>东京</del></td><td>不适用</td><td>不适用</td><td><a data-footnote-ref href="#user-content-fn-9"><del>233.2</del></a> <span data-gb-custom-inline data-tag="emoji" data-code="274c">❌</span></td><td>24.2</td></tr></tbody></table>

</details>

{% hint style="warning" %}
规则 `延迟`  是 **可选，并且只能在你的初始配置中定义一次** 规则。
{% endhint %}

一些玩家对所有信标的网络延迟很高，原因是 互联网服务提供商[^10] 问题或连接较慢（例如无线/移动）可能导致延迟并降低其他人的游戏体验。为缓解此问题：

* 逐步扩大允许的最大延迟和差异（参见 [高级示例配置](/zh/learn/pi-pei.md#advanced-example)),
  * 延迟高的玩家可能需要比平时更长时间才能找到匹配。
* 或者，允许玩家通过手动区域选择来覆盖测量，只为玩家选择的区域发送伪造的延迟值（例如为快速匹配设置为25毫秒），
  * 这可能会对该玩家的队友和对手的游戏体验产生负面影响。

{% hint style="info" %}
**高信标延迟并不总是导致高服务器延迟**。部署点比信标地点更多。信标会实时编排以优先考虑全球覆盖和可靠性。
{% endhint %}

{% hint style="success" %}
参见 [匹配](/zh/learn/pi-pei.md) 用于 **使用我们的 SDK 进行自动化延迟测量**.
{% endhint %}

{% hint style="danger" %}
信标会在实时中自动重新调整规模——添加/移除/替换现有信标。您的客户端和后端应考虑到这一点并 **在每轮匹配之前重新加载信标列表**.
{% endhint %}

**`intersection`** 匹配具有一个或多个重叠字符串值的玩家，区分大小写。

<details>

<summary>规则示例： <code>selected_map</code></summary>

`selected_map` 上述规则，配合 `"重叠": 1`  将匹配：

:white\_check\_mark: Alice + Bob + Charlie 可以匹配，或 Alice + Bob + Dave 可以匹配，

:x: Alice + Bob + Charlie + Dave 永远不会匹配。

<figure><img src="/files/ea62a0c409f89755947d208d6230cabf1aab6af6" alt=""><figcaption></figcaption></figure>

</details>

#### 规则扩展

可选地， **`扩展`**  在队列中等待一段时间后修改规则属性，以放宽限制并扩大可匹配的玩家范围， **从而更快达成匹配**.

<details>

<summary>示例场景：扩展</summary>

[最初，我们要求 1 个队伍，由恰好 4 名玩家组成（可能分成多个小队）](/zh/learn/pi-pei.md#advanced-example) ，满足：

* 相对于同一个（任意一个）信标的最大 125 毫秒延迟，
* 同一信标的最低/最高值之间延迟差不超过 125 毫秒，
* 最低和最高段位玩家之间的技术评分差不超过 50 分，
* 完全相同（区分大小写）的所选游戏模式，
* 玩家之间至少有一个匹配的地图选择（区分大小写），
* 至少有一个匹配的 [补位小队大小](#backfill-match) 值。

在上面的示例中，我们 **通过修改属性来扩展搜索** 在以下条件后：

<table data-view="cards"><thead><tr><th></th><th></th></tr></thead><tbody><tr><td>30 秒：</td><td><ul><li>4 名玩家</li><li><strong>150 分技术评分范围</strong></li><li><strong>最大 250 毫秒延迟</strong></li></ul></td></tr><tr><td>60 秒：</td><td><ul><li>4 名玩家</li><li><strong>200 技能评分范围</strong></li><li>最大 250 毫秒延迟</li></ul></td></tr><tr><td>3 分钟（180 秒）：</td><td><ul><li><strong>1-4 名玩家</strong></li><li>200 技能评分范围</li><li><strong>任意延迟</strong></li></ul></td></tr></tbody></table>

</details>

{% hint style="info" %}
任何规则属性的扩展将会 **覆盖之前的值** 该属性的值。
{% endhint %}

{% hint style="success" %}
[**了解匹配中的常见陷阱**](https://edgegap.com/blog/how-session-fill-rate-affects-your-multiplayer-hosting-costs)**，而** [**使用我们的指南优化你的对局填充率**](https://edgegap.com/blog/how-to-optimize-session-fill-rate-in-your-matchmaker)**.**
{% endhint %}

## 📌 注入变量

你的服务器可能需要了解其玩家的详细信息。玩家属性、解析后的对局值以及其他值会连同常规内容一起注入到你的部署中 [应用与版本](/zh/learn/bian-pai/application-and-versions.md#injected-variables).

预览未格式化内容 **🏁 高级示例变量：**

```
MM_MATCH_PROFILE=advanced-example
MM_EXPANSION=initial
MM_TICKET_IDS=["cusfn10msflc73beiik0","cusfn18msflc73beiil0"]
MM_TICKET_cusfn10msflc73beiik0={"id":"cusfn10msflc73beiik0","created_at":"2025-02-21T22:17:42.3886970Z","player_ip":"174.93.233.25","group_id":"b2080c27-19c9-4fb0-8fe7-4bf1e5d285d1","team_id":"cusfn1gmsflc73beiim0","attributes":{"beacons":{"Chicago":12.3,"LosAngeles":145.6,"Tokyo":233.2},"elo_rating":1337,"selected_game_mode":"quickplay","selected_map":["DustII","Airport","BankVault"],"backfill_group_size":["new","1"]}}
MM_TICKET_cusfn18msflc73beiil0={"id":"cusfn18msflc73beiil0","created_at":"2025-02-21T22:17:42.2548390Z","player_ip":"174.93.233.23","group_id":"015d4dc8-6c79-4b5c-bbc6-f309b9787c8f","team_id":"cusfn1gmsflc73beiim0","attributes":{"beacons":{"Chicago":87.3,"LosAngeles":32.4,"Tokyo":253.2},"elo_rating":1339,"selected_game_mode":"quickplay","selected_map":["Island","Airport"],"backfill_group_size":["new","1"]}}
MM_GROUPS={"b2080c27-19c9-4fb0-8fe7-4bf1e5d285d1":["cusfn10msflc73beiik0"],"015d4dc8-6c79-4b5c-bbc6-f309b9787c8f":["cusfn18msflc73beiil0"]}
MM_TEAMS={"cusfn1gmsflc73beiim0":["b2080c27-19c9-4fb0-8fe7-4bf1e5d285d1","015d4dc8-6c79-4b5c-bbc6-f309b9787c8f"]}
MM_MATCH_ID=advanced-example_initial-2025-02-21T22:17:43.3886970Z
MM_INTERSECTION={"selected_map":["Airport"],"backfill_group_size":["new","1"]}
MM_EQUALITY={"selected_game_mode":"quickplay"}
```

{% hint style="info" %}
环境变量是 **以字符串化 JSON 的形式存储**，请使用我们的 SDK 或自定义方法进行解析。
{% endhint %}

{% hint style="success" %}
**服务器可以将玩家连接映射到组和属性** 在玩家将其票证 ID 发送给服务器后。
{% endhint %}

## 🧵 玩家追踪

如果你的玩家遇到任何问题，将其路径追踪到服务器日志会很有帮助。每个 Matchmaker **部署** **将标记分配给玩家的票证 ID** 这样你就可以轻松 [部署](/zh/learn/bian-pai/deployments.md#filter-deployments) 并查找 [部署](/zh/learn/bian-pai/deployments.md#container-logs) 以帮助你排查问题。

{% hint style="success" %}
**在客户端对局历史界面中显示票证 ID 和部署 ID** 以便在排查问题时追踪玩家。
{% endhint %}

{% hint style="info" %}
请参见 [部署](/zh/learn/bian-pai/deployments.md#connection-quality) 以了解部署故障排除。
{% endhint %}

## 👀 分析

无需代码或配置即可深入了解你的匹配器负载和性能。

🌟 [**将 Matchmaker 升级到企业级**](https://app.edgegap.com/matchmaker-management-v2/matchmakers/list) **以解锁匹配指标和洞察：**

<figure><img src="/files/56c8e797d71b26400d21fc05b4906cbb3550c085" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/fe336e104160c7ca13ac77fe271b566f1b4f4e0f" alt=""><figcaption></figcaption></figure>

## ☁️ 托管集群

Matchmaker 由 Edgegap 便捷地全天候 24/7 托管和管理。

选择最适合你的目标的托管选项：

* **免费集群（共享）** 用于测试所有功能并探索与您的设计的协同效应，
  * 会在 3 小时后自动关闭，需要重启才能继续测试。
* **私有集群** **（专用）** 以确保为您的生产需求提供稳定的环境，
  * 选择您的区域并为实时游戏获得 24/7 支持，以便自信发布。

#### 私有集群等级

我们目前提供 [3 个私有集群等级](https://edgegap.com/resources/pricing#managed-infrastructure) 以满足每个人的需求：

<table><thead><tr><th width="160">等级</th><th align="right">爱好者等级</th><th align="right">工作室等级</th><th align="right">企业等级</th></tr></thead><tbody><tr><td>最适合用于</td><td align="right">爱好者，<br>独立开发者</td><td align="right">商业发布</td><td align="right">高流量上线</td></tr><tr><td>资源</td><td align="right">1 vCPU + 2GB 内存</td><td align="right">6 vCPU + 12GB 内存</td><td align="right">18 vCPU + 48GB 内存</td></tr><tr><td>冗余</td><td align="right">1 个虚拟节点</td><td align="right">3 个虚拟节点</td><td align="right">3 个虚拟节点</td></tr><tr><td>限流（请求/秒）</td><td align="right">200</td><td align="right">750</td><td align="right">2,000</td></tr><tr><td>价格，每小时</td><td align="right">$0.0312</td><td align="right"> $0.146</td><td align="right">$0.548</td></tr><tr><td><strong>价格，30 天</strong><br>（持续使用）</td><td align="right"><strong>$22.464</strong></td><td align="right"><strong>$105.12</strong></td><td align="right"><strong>$394.56</strong></td></tr></tbody></table>

一键升级到私有集群。在上线后也可以在不影响玩家停机的情况下更改私有集群等级，借助 [#rolling-updates-and-ab-tests](#rolling-updates-and-ab-tests "mention")。托管集群提供由 Edgegap 维护的高可用服务托管，并为已正式发布的游戏提供 24/7 实时支持。

你的实例资源需求将取决于以下因素：

* **玩家数量** - 更多玩家会产生更多票证和 API 请求，
* **每位玩家的请求次数** - 更快的重试会增加服务负载并消耗资源，
* **配置复杂度** - 交集规则和扩展尤其耗费资源，
* **平均对局时长** - 更短的会话会让玩家更频繁地重新进入匹配，
* **过期和移除周期** - 过期票证会随着时间堆积并消耗资源，
* **客户端重试回退逻辑** - 使用带抖动的退避重试有助于分散流量突发峰值。

{% hint style="warning" %}
**为成功做好准备，并在上线后进行优化，这样你就不会在发布当天阻塞你的玩家。** 使用 [开发者工具](/zh/unity/developer-tools.md#matchmaking-sdk) 或 **实现指数抖动退避** 以从高负载中恢复。
{% endhint %}

{% hint style="info" %}
我们的集群使用配备 AMD/Intel CPU 的云主机，主频为 2.4 - 3.2 GHz。
{% endhint %}

## ⏩ 滚动更新 <a href="#rolling-updates-and-ab-tests" id="rolling-updates-and-ab-tests"></a>

跟踪服务器和客户端版本之间的兼容性可能会很复杂。请遵循我们的建议，以实现可靠的发布、更新，并防止停机或兼容性问题。

**重启后，你的 Matchmaker URL 和认证令牌将始终保持不变。**

{% hint style="danger" %}
**为开发和生产环境创建独立的 matchmaker** 以便安全地进行实验。
{% endhint %}

#### ⚠️ **正式上线前**

我们建议提前创建多个 matchmaker 副本： `绿色`, `蓝色` 和 `橙色`。在发布更新时，你可以轮换正在使用的 matchmaker（[蓝绿策略](https://en.wikipedia.org/wiki/Blue%E2%80%93green_deployment)).

**为每个实例选择不同区域，以防止停机** 在局部故障期间。

<figure><img src="/files/0fe9ed0348855c264917ec43225763578e1a195b" alt=""><figcaption><p>蓝绿 DevOps 环境示例</p></figcaption></figure>

#### **🔃 客户端 + 服务器更新**

**前提条件：** 本节假定你已完成 [#before-going-live](#before-going-live "mention").

为了 **发布游戏客户端 + 服务器更新**，你可以：

1. 准备新的服务器应用版本 `v1.2.0-rc` 在 Edgegap 上：
   1. 将新的镜像标签推送到你的容器注册表 `t1.2.0`,
   2. 创建新的应用版本 `v1.2.0-rc`,
2. 通过以下方式执行任何开发测试： [部署你的新应用版本](https://app.edgegap.com/deployment-management/deployments/list) `v1.2.0-rc`:
   1. 将你的游戏引擎编辑器连接到提供的 URL + 外部端口，
3. 更新未使用的 matchmaker `蓝色` 以链接到你的新镜像标签 `t1.2.0`,
   1. 为新应用版本启用缓存 `v1.2.0-rc` ，为此版本启用缓存将确保该镜像也会被缓存到版本 `v-blue`  因为它们引用的是同一个标签，
   2. 等待版本中的缓存指示器 `v1.2.0-rc`  达到 :green\_circle: 绿色，
4. 更新你的新游戏客户端 `c2` 以使用新版本 `v-blue` 在创建票证时：
   1. 在游戏客户端中更新你的基础 URL 和授权令牌，
5. 对你的新游戏客户端进行 QA 测试和最终验证 `c2`:
   1. 如果你发现并解决了任何问题，请从头重复此过程，
   2. 等待 3-7 天，让 matchmaker 的 DNS 更改传播到全球各地的 ISP；在 matchmaker 停止后（快速重启不需要 DNS 更新或等待期），
6. 发布你的新游戏客户端更新 `c2` 在游戏分发平台上，
7. 给新游戏客户端留出时间 `c2` 分发到玩家设备（通常最多 3-7 天）：
   1. 监控过时的游戏客户端 `c1`  使用部署 [部署](/zh/learn/bian-pai/deployments.md#analytics),
8. 清理你 Edgegap 账户中未使用的资源：
   1. 删除镜像标签 `t1.0.0` 以释放容器注册表容量，
   2. 删除镜像标签 `t1.1.0` 以释放容器注册表容量，
   3. 关闭你的 `绿色`  matchmaker，以暂停计费直到你的下一次更新。

{% hint style="success" %}
**对于下一次更新**，提高版本号并交换 `绿色` 和 `蓝色` 指南中的关键词。
{% endhint %}

#### **⚡ 服务器热修复**

**前提条件：** 本节假定你已完成 [#before-going-live](#before-going-live "mention").

为了 **在不需要游戏客户端更新的情况下发布服务器补丁**，你可以：

1. 准备新的服务器应用版本 `v1.2.0-rc` 在 Edgegap 上：
   1. 将新的镜像标签推送到你的容器注册表 `t1.2.0`,
   2. 创建新的应用版本 `v1.2.0-rc`,
2. 通过以下方式执行测试和验证： [部署你的新应用版本](https://app.edgegap.com/deployment-management/deployments/list) `v1.2.0-rc`:
   1. 将你的游戏引擎编辑器连接到提供的 URL + 外部端口，
   2. 如果你发现并解决了任何问题，请从头重复此过程，
   3. 为新应用版本启用缓存 `v1.2.0-rc` ，为此版本启用缓存将确保该镜像也会被缓存到版本 `v-green`  稍后，因为它们将引用同一个标签，
   4. 等待版本中的缓存指示器 `v1.2.0-rc`  达到 :green\_circle: 绿色，
3. 更新版本 `v-green`  以链接到你的新镜像标签 `t1.2.0`,
   1. 新的对局将自动使用更新后的标签开始分配 `t1.2.0`,
   2. 监控过时的游戏客户端 `c1`  使用部署 [部署](/zh/learn/bian-pai/deployments.md#analytics),
4. 清理你 Edgegap 账户中的未使用资源：
   1. 删除镜像标签 `t1.1.0` 以释放容器注册表容量。

## 📗 API <a href="#matchmaking-api" id="matchmaking-api"></a>

客户端和服务器可以直接调用 API，或通过游戏引擎 SDK 调用，另请参阅 [匹配](/zh/learn/pi-pei.md).

{% hint style="info" %}
Unity/Android - 考虑 [使用原始字符串插值](https://www.c-sharpcorner.com/article/convert-string-to-json-in-c-sharp/) 以防止对硬编码 JSON 的代码剥离。
{% endhint %}

{% hint style="success" %}
**Swagger Web UI**：部署您的服务将生成一个 OpenAPI 规范和一个便捷的网页 UI。在浏览器中打开该 URL 以查看和测试所有 API 端点，并审查示例负载。
{% endhint %}

{% tabs fullWidth="false" %}
{% tab title="🍀 简单示例" %}
{% file src="/files/3f48de4d14fea1d589ad785e9730695a062c38eb" %}
{% endtab %}

{% tab title="🏁 高级示例" %}
{% file src="/files/6f6319774f9650dd7371595fdd7f4b132340ee1c" %}
{% endtab %}

{% tab title="🎾 自定义大厅" %}
{% file src="/files/5c46537fd89f053c32ecf3efd3b2146952739d1d" %}
{% endtab %}

{% tab title="🥛 回填展示" %}
{% file src="/files/a1aabfbd3ec2944a21bba8b2222625ed3d8fa759" %}
{% endtab %}

{% tab title="⚔️ 竞技游戏" %}
{% file src="/files/79c201866d4b9952d11b7cdb8bdbccc64ddb249f" %}
{% endtab %}

{% tab title="🤝 合作游戏" %}
{% file src="/files/4050e58da314beb3c7d257346e6489a434d2b1cc" %}
{% endtab %}

{% tab title="🎈 社交游戏" %}
{% file src="/files/e9faff81678425eb54e627ce7c766f61db0e39b6" %}
{% endtab %}
{% endtabs %}

将 API 规范导入到 [Scalar API Web 客户端](https://client.scalar.com/workspace/default/request/default) 注入的变量（Injected Variables） [Swagger 编辑器](https://editor.swagger.io/) 以查看详细信息。

### 速率限制

为了保护你的集群不超过其突发容量并崩溃，我们会基于内部负载测试限制每秒请求数，使用 [匹配](/zh/learn/pi-pei.md#advanced-example) 配置。

<table><thead><tr><th>API 端点</th><th width="130">免费套餐</th><th width="130">爱好者套餐</th><th width="130">工作室套餐</th><th width="130">企业套餐</th></tr></thead><tbody><tr><td><strong>总体限制</strong></td><td><strong>100</strong></td><td><strong>200</strong></td><td><strong>750</strong></td><td><strong>2,000</strong></td></tr><tr><td>创建部署</td><td>5</td><td>10</td><td>30</td><td>30</td></tr><tr><td>列出信标</td><td>10</td><td>20</td><td>75</td><td>200</td></tr><tr><td>创建组<br>+ 创建票证<br>+ 创建组票证</td><td>10</td><td>20</td><td>75</td><td>200</td></tr><tr><td>读取成员关系<br>+ 读取组<br>+ 读取票证</td><td>10</td><td>120</td><td>450</td><td>1,300</td></tr><tr><td>创建回填</td><td>5</td><td>10</td><td>37</td><td>100</td></tr></tbody></table>

速率限制以 **针对指定 API 端点集合的合并每秒请求数来表示**.

{% hint style="warning" %}
如果你的游戏客户端在收到响应后不重试请求 `429 请求过多` **你的部署可能会缺少玩家** 在短暂突发和流量高峰期间。
{% endhint %}

#### 负载测试

在类似生产环境中进行负载测试会产生部署托管成本。请参见各层级对应的资源和价格 [我们的定价页面](https://edgegap.com/resources/pricing#matchmaker).

{% hint style="warning" %}
**使用** [**私有集群**](#private-cluster-tiers) **用于压力测试。** 免费实例严格仅限于开发测试。
{% endhint %}

在设计负载测试时， **请考虑真实的玩家行为模式**:

| 真实场景                                  | 不现实的流量模式                       |
| ------------------------------------- | ------------------------------ |
| ✅ 玩家逐步加入游戏，在数小时内逐渐提升请求/秒。             | ❌ 所有玩家协调一致，在完全相同的一秒内访问 API。    |
| ✅ 玩家在重试之间等待的时间逐步增加（例如 1s-5s-10s-10s）。 | ❌ 所有玩家在收到后立即重试 `429 请求过多`  响应。 |
| ✅ 大多数玩家会在较短时间内（10-60 秒）收到分配并停止轮询。     | ❌ 所有玩家在收到分配后仍会继续轮询一段固定时间。      |
| ✅ 大多数玩家在重新开始新会话之前会先完成当前游戏（需要一些时间）。    | ❌ 所有玩家在收到服务器分配后立即重新开始新的会话。     |
| ✅ 峰值流量每天持续约 6 小时，之后部分时区的流量会下降。        | ❌ 峰值流量全天 24 小时持续，所有玩家日夜不停地玩。   |

#### 负载下的行为

如果 matchmaker 正承受高负载：

* 如果 CPU 被限频，匹配可能会变慢，
* 如果 matchmaker 内存耗尽，它会在不丢失票证信息的情况下重启，希望客户端实现指数退避，并将突发流量分散到更长时间内。

#### 跨域资源共享（CORS）

对于托管在第三方分发平台上的 WebGL 游戏（例如 [itch.io](http://itch.io/)），从游戏客户端向 Matchmaker 发送任何请求都可能导致 [跨域资源共享](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) 策略违规。大多数现代网页浏览器会发送一个 [预检请求](https://developer.mozilla.org/en-US/docs/Glossary/Preflight_request) 以验证后端服务（Matchmaker）是否理解并接受来自你的游戏客户端的通信。

预检检查失败（出于安全原因这是默认行为）可能会导致 [以下几种可能的 CORS 相关错误之一](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS/Errors/CORSMissingAllowOrigin)，最常见的是 `缺少 CORS 响应头 'Access-Control-Allow-Origin'` .

要解决此错误，请添加 **`allowed_cors_origin`** 参数到你的配置中，以便：

* 将你的确切客户端托管域名列入白名单：

<details>

<summary>🍀 简单示例（特定域名示例）</summary>

<pre class="language-json"><code class="lang-json">{
  "version": "3.2.3",
  "allowed_cors_origins": [
    "https://dev.my-game-server.com",
    "https://prod.my-game-server.com"
  ],
  "配置文件": {
      <a data-footnote-ref href="#user-content-fn-11">...</a>
  }
}
</code></pre>

</details>

* 或者将通配符域名（包括所有子域）列入白名单：

<details>

<summary>🍀 简单示例（通配符域名示例）</summary>

<pre class="language-json"><code class="lang-json">{
  "version": "3.2.3",
  "allowed_cors_origins": ["https://*.my-game-server.com"],
  "配置文件": {
      <a data-footnote-ref href="#user-content-fn-11">...</a>
  }
}
</code></pre>

</details>

{% hint style="info" %}
**Matchmaker 预检请求不需要凭证**，前提是域名配置正确。
{% endhint %}

### 服务器到服务器 <a href="#server-to-server-api" id="server-to-server-api"></a>

通过我们的自定义代理，为匹配流程添加增强或自定义控制——使用我们的 [托管集群](/zh/learn/advanced-features/managed-clusters.md) 或任何云 FaaS[^12] 计算平台，以实现以下任一目的：

* 附加敏感玩家属性——例如作弊标记、技能评级或类似信息，
* 在游戏中提供队伍和对局上下文——在加载期间列出我的队友和对手，
* 限制特定边缘情况——例如允许每个玩家在任何时候只属于 1 个组，
* 添加缓存或 API 速率限制——减少请求数量和对 matchmaker 的负载，
* 自定义大厅-组集成——在匹配前创建非对称/基于角色的大厅。

{% hint style="success" %}
**包含参数 `player_ip`  以及成员的公网 IP 地址** 以确保尽可能低的玩家延迟，并利用 [/pages/5e7e2169ca3822647d4607dfc1d3487ebcc0836c#id-1.-server-score-strategy-best-practice](https://docs.edgegap.com/zh/learn/pi-pei/pages/5e7e2169ca3822647d4607dfc1d3487ebcc0836c#id-1.-server-score-strategy-best-practice "mention").
{% endhint %}

{% hint style="info" %}
游戏客户端可以使用 [ipify.org](http://ipify.org/) 免费服务来查找其公网 IP。VPN 可能会隐藏公网 IP 地址。
{% endhint %}

<figure><img src="/files/3dd27636b26aabb17b7f1e8bb57aa66a25ddb039" alt=""><figcaption><p>服务器到服务器匹配活动图</p></figcaption></figure>

## 🚨 故障排除

**你的成功是我们的首要任务。** 如果你想发送自定义请求、提出缺失的关键功能，或表达任何想法， [请在我们的社区 Discord 中联系我们](https://discord.gg/MmJf8fWjnt).

<details>

<summary><code>应用配置对于配置文件 XYZ 无效。</code></summary>

* 我们找不到您的 [应用与版本](/zh/learn/bian-pai/application-and-versions.md)，请验证 `应用`  值。

</details>

<details>

<summary><code>标签为 '2024.01.30-16.23.00-UTC' 的 Docker 镜像未被缓存。</code></summary>

[**🌟 升级到按需付费等级**](https://app.edgegap.com/user-settings?tab=memberships) **以解锁** [**具有缓存的即时部署**](https://docs.edgegap.com/zh/learn/pi-pei/pages/5e7e2169ca3822647d4607dfc1d3487ebcc0836c#id-1.-start-a-deployment)**.**

* 4GB 以上未缓存的镜像可能需要更长时间部署，导致 [/pages/5e7e2169ca3822647d4607dfc1d3487ebcc0836c#id-4.-deployment-error](https://docs.edgegap.com/zh/learn/pi-pei/pages/5e7e2169ca3822647d4607dfc1d3487ebcc0836c#id-4.-deployment-error "mention")。请考虑优化您的服务器镜像大小（[虚幻引擎](/zh/unreal-engine.md#optimize-server-build-size) / [Unity](/zh/unity.md#optimize-server-build-size)).
* 您仍然可以继续，但我们建议测试您的部署时间。

</details>

<details>

<summary>为什么我在尝试创建新的 matchmaker 时会出错？</summary>

* 请阅读错误信息，可能是你拼错了标识符、规则或运算符。- 使用 [JSONLint](https://jsonlint.com/) 来验证你的 JSON 格式，你可能漏了一个逗号或括号。- 通过 [我们的社区 Discord](https://discord.gg/MmJf8fWjnt) 寻求帮助，我们很乐意提供协助。🙏

</details>

<details>

<summary>为什么我的 matchmaker 会在 3 小时后自动关闭？</summary>

* 免费套餐中的 matchmaker 仅用于初始测试，并会在 3 小时后自动关闭。要继续测试，你可以 [重启你的 matchmaker](https://app.edgegap.com/matchmaker-management-v2/matchmakers/list).
* 考虑升级到付费套餐以获得无限运行时间。

</details>

<details>

<summary>为什么我无法在我的账户上启动第二个部署？</summary>

* 免费套餐中你只能同时运行 1 个部署。
* 请考虑升级到付费套餐以获得无限部署。

</details>

<details>

<summary>为什么我会在随机时间收到分配/部署，而不考虑 <code>player_count</code>?</summary>

* 你或其他团队成员可能在之前的测试会话中创建了尚未分配的票证。请 [重启你的 matchmaker](https://app.edgegap.com/matchmaker-management-v2/matchmakers/list).

</details>

<details>

<summary>我的票证卡在 <code>SEARCHING</code> .</summary>

* 请确认你已按照你的配置创建了足够多的匹配票证。

</details>

<details>

<summary>我的票证卡在在以下状态之间切换： <code>MATCH_FOUND</code> 和 <code>TEAM_FOUND</code> 反复。</summary>

* 免费套餐账户一次仅限 1 个部署。
* 请考虑升级，或停止当前部署以启动新的部署。

</details>

<details>

<summary>我的票证直接进入 <code>CANCELLED</code>.</summary>

* 你的票证已到达其过期时间。请创建新票证，或增加配置中的过期时长以供测试。

</details>

<details>

<summary>我收到 <code>HTTP 404 Not Found</code> 当我检查票证时。</summary>

* 你的票证已通过 DELETE 请求删除，或因达到其移除时长（在票证过期后开始，由你的配置定义）而被删除。请重新创建新票证，或增加配置中的过期/移除时长以供测试。

</details>

<details>

<summary>我的 matchmaker 显示错误，我该怎么办？</summary>

* 如果这是开发或测试实例，请先尝试重启你的 matchmaker。- 请通过以下方式报告任何问题 [我们的社区 Discord](https://discord.gg/MmJf8fWjnt).
* 如果此问题影响到线上游戏，请创建一个 [紧急支持请求](https://edgegap.atlassian.net/servicedesk/customer/portal/3).

</details>

## 🔖 更新日志

#### 语义化版本控制

我们的开发者工具和托管服务使用官方 [语义化版本控制](https://semver.org/)，表明哪些更新是✅安全的（次要、补丁），哪些可能包含⚠️破坏性更改（主要）。

**一旦某个版本发布，它将永远不会被修改/更改**.

你的配置文件将根据所使用的 matchmaker 版本进行验证，请确保你的规则与该 matchmaker 版本的能力相匹配。

{% hint style="info" %}
**matchmaker 的最新版本是 `3.2.5`**。本页中的所有示例均为最新。

请留意 [更新和公告](/zh/docs/release-notes.md)。另请参阅 [#rolling-updates-and-ab-tests](#rolling-updates-and-ab-tests "mention").
{% endhint %}

{% hint style="warning" %}
**要升级你的 matchmaker 版本——停止、编辑、重启。** 快速重启不会应用版本更改。
{% endhint %}

[^1]: 示例值

[^2]: 游戏客户端加入大厅以获取匹配组 ID 并加入该小队

[^3]: 完全限定域名

[^4]: 例如，3 个空位 = \["3", "2", "1"]

[^5]: 将“2”替换为实际组成员数量

[^6]: 替换为你自己的应用名称

[^7]: 替换为你自己的应用版本

[^8]: 超过最大差值

[^9]: 超过最大延迟

[^10]: 互联网服务提供商（ISP）

[^11]: 查看其他示例

[^12]: [函数即服务](https://www.ibm.com/think/topics/faas)
