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

# 匹配系统

使用 Edgegap 可选的入门套件 SDK，为你的 Unity 游戏添加匹配系统；它可随你的多人项目增长而扩展和自定义。

此 SDK 是面向 Unity 用户的可选入门套件，后续可扩展和自定义。

## 💡 功能

{% columns %}
{% column %}

* 完整示例
* Ping 自动化
* 票据、组、队伍
  {% endcolumn %}

{% column width="33.33333333333333%" %}

* 匹配变量
* 类型定义（C#）
* 本地开发测试
  {% endcolumn %}

{% column width="33.33333333333333%" %}

* 跨平台
* 易于自定义
* 自动重试
  {% endcolumn %}
  {% endcolumns %}

## ✔️ 准备

Unity SDK 包含用于 Deployments、Matchmaking 和 Server Browser 的可选集成工具。此插件官方支持 Unity 2021.3.0f1 及更高版本。

{% hint style="info" %}
**Unity SDK 的最新版本是 `3.5.4`**。本文档中的所有示例均为最新。
{% endhint %}

{% hint style="success" %}
此插件完全免费提供，受 Free Tier 的条款和条件约束。
{% endhint %}

#### 要求

<details>

<summary>安装 Git 客户端（例如 <a href="https://git-scm.com/">git-scm</a>)</summary>

Unity 需要 git 客户端才能自动下载并安装我们的 Unity 包。安装后，你无需直接使用 git。

</details>

#### 安装

1. 打开你的 Unity 项目，
2. 选择 `窗口 > 包管理 > 包管理器` ,
3. 点击 :heavy\_plus\_sign: 图标并选择 `从 git URL 添加包...` ,
4. 在提示时输入我们 SDK 的 URL：

{% code title="" %}

```
https://github.com/edgegap/edgegap-unity-sdk.git
```

{% endcode %}

5. 点击 `添加`  并等待安装完成。

#### 导入示例

此包包含多个示例，旨在单独使用（不要将示例组合使用）。

#### 已验证来源

这是此 SDK 唯一的官方分发渠道，不要相信未经验证的来源！

#### 更新包

在 Unity Package Manager 中导航到 Edgegap SDK 并点击 `更新` .

{% hint style="warning" %}
**已导入的示例不会自动更新！** 备份任何自定义属性值，删除当前场景中使用的示例脚本，然后重新导入示例。
{% endhint %}

{% hint style="info" %}
某些版本可能包含破坏性更改。这将由新的 MAJOR 版本指示。
{% endhint %}

#### 更新到 v3

此更新包含许多新的 [服务器浏览器](/zh/unity/server-browser.md) 工具和示例，改进了匹配错误处理，等等。请参见 [发行说明](/zh/docs/release-notes.md) 了解完整列表。

{% hint style="warning" %}
Unity SDK v3 更新包含一些破坏性更改。请仔细重新测试你的集成。
{% endhint %}

## 🍀 入门

本指南假设你对 [匹配系统](/zh/learn/pi-pei-xi-tong.md) 概念有基本了解，并且已有一个运行中的 Matchmaker。

{% hint style="success" %}
**我们强烈建议导入我们的 Simple Example** ，以便在阅读本文档时跟着代码一起操作。你可以在以下位置进行： `Unity Package Manager > Edgegap SDK > Samples` .
{% endhint %}

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

### 概览

我们的 SDK 大量使用 [依赖注入](https://learn.microsoft.com/en-us/dotnet/core/extensions/dependency-injection/overview#the-concept) 和 [观察者](https://learn.microsoft.com/en-us/dotnet/standard/events/observer-design-pattern) 编程模式。

{% hint style="info" %}
此包整合了这两者 [服务器浏览器](/zh/learn/fu-wu-qi-liu-lan-qi.md) 和 [匹配系统](/zh/learn/pi-pei-xi-tong.md)，它们可以一起使用，也可以单独使用。您可以自由重用任何脚本，用于您自己的定制分支和集成。
{% endhint %}

此包包含：

* 运行时文件 - 将被编译并打包到你的客户端和服务器构建中：
  * 服务特定工具：
    * [#client-agent](#client-agent "mention") - 一个完整的客户端集成，可供复用/扩展。
    * API 函数 - 端点定义、错误处理和日志自动化。
  * 服务特定 DTO[^1] - 用于 Matchmaking API 的强类型数据容器。
  * 共享工具 - 日志、HTTP、ping、可观察对象等……
  * 共享 DTO[^1] - 被多个 Edgegap 服务用于传递数据。
* 示例文件 - 仅在导入到你的项目中时才会被打包并编译：
  * [#simple-example](#simple-example "mention") - 一个用于 [最小配置](/zh/learn/pi-pei-xi-tong.md#simple-example).
  * [#region-picker](#region-picker "mention") - 探索带有手动区域选择的 UI 集成。

### Group Client

**Ping 自动化、票据管理和主机检索** 由 Group Client 执行。

一旦实例化，agent 的 **父级 Monobehaviour（处理器）必须初始化客户端** 并提供：

* `onMonitorUpdate`  回调 - 观察服务健康状况变化。
* `onAssignmentUpdate`  回调 - 观察并响应主机分配变化。

初始化后，客户端将自动提供验证并挂接日志观察者，最后只需一次调用监控 API 端点来指示服务健康状态。

从此处开始，客户端处理器应接管并调用客户端函数：

* `信标`  以检索可用的列表 [Ping 信标](/zh/learn/bian-pai/ping-beacons.md).
* `MeasureBeaconsRoundTripTime`  用于针对一组给定信标提供 ping 测量。
* `CreateGroup`  供大厅房主创建可加入的组，朋友可被邀请加入。
* `JoinGroup`  使用通过第三方大厅/后端发送的组 ID 加入现有组。
* `SetReady`  将组所有者和成员标记为就绪，并开始搜索匹配。
* `ResumeMatchmaking`  加载缓存的组，并在客户端崩溃时继续搜索。
* `StopMatchmaking`  删除票据（如果尚未匹配）并放弃队列。
* `状态`  用于验证 Matchmaker 服务健康状态。

当建立新的玩家连接时，玩家应使用你的网络代码将其票据 ID 发送到游戏服务器，以将连接与 [深入了解](/zh/learn/pi-pei-xi-tong/matchmaker-in-depth.md#injected-variables).

{% hint style="success" %}
将连接详情保存在客户端或游戏后端，以便在发生意外崩溃时重新连接。
{% endhint %}

## 服务器代理

服务器代理执行 **回填创建、检测票据分配、检测回填放弃和移除。它还会跟踪并重新创建已过期、连接宽限期已结束或已被放弃的回填——以达到所需的队伍人数**.

服务器代理会跟踪当前已连接的玩家，并自动将他们的票据包含到新的回填中，以确保回填玩家会根据所配置配置文件的规则进行匹配。

一旦实例化，agent 的 **父级 Monobehaviour（处理器）必须初始化客户端** 并提供：

* `onMonitorUpdate`  回调 - 观察服务健康状况变化。
* `onBackfillUpdate` 回调 - 观察并响应回填变化。

初始化后，客户端将自动提供验证并挂接日志观察者，最后只需一次调用监控 API 端点来指示服务健康状态。

从此处开始，服务器处理器应接管并调用客户端函数：

* `PlayerConnected`  以防止替换从未连接的初始玩家或回填玩家。
* `AbandonPlayer`  用于指示一名已连接玩家离开服务器并需要被替换。
* `AbandonAllBackfills`  用于立即停止服务器回填并删除回填。
  * 应在停止服务器之前调用此方法。此时已经分配到的玩家需要重新加入匹配，因为服务器正在关闭。
  * 在调用此方法时已分配的回填仍可在配置的宽限期内连接。
* `AbandonBackfill`  用于强制放弃某个特定回填（自定义处理器实现）。
* `状态`  用于验证匹配器服务健康状态。

## 🧪 示例

从示例开始，其中包括服务端和客户端的完整可运行集成。

### Simple Example

包含完整的玩家生命周期实现，具备 ping 测量、票据管理和主机分配获取功能。演示如何在服务器端读取注入的匹配变量。

修改匹配属性即可轻松扩展此示例，以适配任何配置。

### Region Picker

某些玩家（或组）具有特殊的本地条件（例如 ISP[^2] 封锁， 全国范围封锁[^3]，或其他情况），他们可能更倾向于手动选择区域，而不是仅依据 ping。

查看我们的 Region Picker 示例，并从中获取匹配 UI 实现的灵感。

### 组队

与一组好友一起加入匹配队列，要求所有玩家在开始搜索前确认。先从一个最小 UI 实现开始，然后再根据你的游戏设计进行自定义。

探索与组队流程的 UI 集成，提供尽可能好的社交体验。

### 回填

复用服务器容量并向正在进行的部署中添加玩家。设置目标队伍人数并等待玩家加入。包含自动连接宽限期以及重新创建已过期回填。

为多队伍或不对称队伍配置自定义示例服务器处理器。

## ⚙️ 自定义

此 SDK 旨在扩展和修改，不过某些修改可能有风险：

✅ Handler - 可安全连接 UI 观察者并进行小幅添加或修改，

⚠️ Agent - 修改玩家生命周期管理需自担风险，

⚠️ API - 使用精选工具从头编写你自己的集成。

处理器可以观察下方所述由 Server 和 Client agent 发出的任何事件。

{% hint style="warning" %}
务必先熟悉 [深入匹配](/zh/learn/pi-pei-xi-tong/matchmaker-in-depth.md) 概念，再进行自定义。
{% endhint %}

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

### 客户端事件

Group Client 会发出事件（操作），供父级处理器观察和消费。

{% hint style="success" %}
通过访问读取事件载荷  `.Current` 任何可观察对象的状态。🔴 `错误` 事件在主事件消息之后包含由换行符分隔的完整错误消息。
{% endhint %}

预览由可观察对象发出的事件 `监控` :

<table data-full-width="true"><thead><tr><th width="125">操作类型</th><th width="450">事件消息</th><th>描述</th></tr></thead><tbody><tr><td>🟢 <code>更新</code> </td><td><code>健康</code></td><td>所有系统正常。</td></tr><tr><td>🟢 <code>更新</code> </td><td><code>不健康</code></td><td>意外问题。</td></tr><tr><td>🔴 <code>错误</code></td><td><code>获取监控失败</code></td><td>配置错误或意外问题。</td></tr><tr><td>🔴 <code>错误</code></td><td><code>获取信标失败</code></td><td>意外问题。</td></tr></tbody></table>

预览由可观察对象发出的事件 `组`:

<table data-full-width="true"><thead><tr><th width="125">操作类型</th><th width="450">事件消息</th><th>描述</th></tr></thead><tbody><tr><td>🟢 <code>更新</code> </td><td><code>已创建</code></td><td>组创建成功。</td></tr><tr><td>🔴 <code>错误</code></td><td><code>组创建失败</code></td><td>创建组失败。</td></tr><tr><td>🟢 <code>更新</code> </td><td><code>已加入</code></td><td>组加入成功。</td></tr><tr><td>🔴 <code>错误</code></td><td><code>加入组失败</code></td><td>加入组失败。</td></tr><tr><td>🟢 <code>更新</code> </td><td><code>已恢复</code></td><td>组恢复成功。</td></tr><tr><td>🔴 <code>错误</code></td><td><code>未找到组</code></td><td>不是组成员，或组已过期。</td></tr><tr><td>🔴 <code>错误</code></td><td><code>冲突，放弃并重新开始</code></td><td>在尝试创建/加入新组之前，请先放弃当前组。</td></tr><tr><td>🟢 <code>更新</code> </td><td><code>成员已更新 [{ready}]</code></td><td>成员已更新为新的 Ready 值。</td></tr><tr><td>🔴 <code>错误</code></td><td><code>成员更新失败</code></td><td>更新组成员失败。组开始搜索匹配后，无法取消就绪。</td></tr><tr><td>🔵 <code>通知</code></td><td><code>轮询 [{consecutive}/{maximum}]</code></td><td>客户端已开始轮询组状态。</td></tr><tr><td>🔵 <code>通知</code></td><td><code>轮询已停止</code></td><td>客户端已停止轮询票据状态。</td></tr><tr><td>🔴 <code>错误</code></td><td><code>轮询失败，已达到最大重试次数</code></td><td>客户端已用尽连续轮询的最大重试次数。请检查服务状态。</td></tr><tr><td>🔴 <code>错误</code></td><td><code>轮询失败</code></td><td>客户端在轮询时收到不可重试的错误。请检查服务状态。</td></tr><tr><td>🟢 <code>更新</code> </td><td><code>组已更新 [{status}]</code></td><td>轮询期间检测到组状态变化。</td></tr><tr><td>🟢 <code>更新</code> </td><td><code>已放弃</code></td><td>票据删除成功。</td></tr><tr><td>🟢 <code>更新</code> </td><td><code>放弃失败（未找到）</code></td><td>客户端找不到要删除的票据，可能已过期。</td></tr><tr><td>🟡 <code>警告</code></td><td><code>放弃失败（已匹配）</code></td><td>客户端无法删除已匹配的组。请禁用放弃或 <a data-mention href="/zh/learn/pi-pei-xi-tong/matchmaker-in-depth.md#backfill-match">深入了解</a> 用于替换该玩家。</td></tr><tr><td>🔴 <code>错误</code></td><td><code>放弃失败</code></td><td>删除组或成员关系失败。</td></tr><tr><td>🟢 <code>更新</code> </td><td><code>已移除</code></td><td>组已过期，本地引用已删除。</td></tr></tbody></table>

### 服务器事件

Server Agent 会发出事件（操作），供父级处理器观察和消费。发出这些事件的 Server Agent 仅在以下内容中初始化： [#backfill](#backfill "mention") 示例。

{% hint style="info" %}
当前已分配的票据可从 Server Agent 属性读取 `分配`  随时。
{% endhint %}

{% hint style="success" %}
通过访问读取事件载荷  `.Current` 任何可观察对象的状态。🔴 `错误` 事件在主事件消息之后包含由换行符分隔的完整错误消息。
{% endhint %}

预览由可观察对象发出的事件 `监控` :

<table data-full-width="true"><thead><tr><th width="125">操作类型</th><th width="450">事件消息</th><th>描述</th></tr></thead><tbody><tr><td>🟢 <code>更新</code> </td><td><code>健康</code></td><td>所有系统正常。</td></tr><tr><td>🟢 <code>更新</code> </td><td><code>不健康</code></td><td>意外问题。</td></tr><tr><td>🔴 <code>错误</code></td><td><code>获取监控失败</code></td><td>配置错误或意外问题。</td></tr></tbody></table>

预览由可观察对象发出的事件 `回填`:

<table data-full-width="true"><thead><tr><th width="125">操作类型</th><th width="450">事件消息</th><th>描述</th></tr></thead><tbody><tr><td>🟢 <code>更新</code> </td><td><code>已创建 [{backfill}]</code></td><td>回填创建成功。</td></tr><tr><td>🔴 <code>错误</code></td><td><code>创建失败</code></td><td>回填出现意外问题。请检查服务状态。</td></tr><tr><td>🔵 <code>通知</code></td><td><code>轮询 [{consecutive}/{maximum}]</code></td><td>轮询失败，正在自动重试。</td></tr><tr><td>🟢 <code>更新</code> </td><td><code>已分配 [{backfill}]</code></td><td>票据已成功分配到回填。</td></tr><tr><td>🔵 <code>通知</code></td><td><code>轮询已停止</code></td><td>轮询已按处理器请求停止。</td></tr><tr><td>🔵 <code>通知</code></td><td><code>轮询失败（未找到）[{backfill}]</code></td><td>未找到，移除引用。回填很可能已过期。</td></tr><tr><td>🔴 <code>错误</code></td><td><code>轮询失败（已达最大重试次数）[{backfill}]</code></td><td>已耗尽重试次数，放弃回填。</td></tr><tr><td>🔴 <code>错误</code></td><td><code>轮询失败 [{backfill}]</code></td><td>出现意外问题，正在移除引用。</td></tr><tr><td>🔵 <code>通知</code></td><td><code>已放弃 [{backfill}]</code></td><td>回填已放弃，正在移除引用。</td></tr><tr><td>🟡 <code>警告</code></td><td><code>放弃失败 [{backfill}]</code></td><td>放弃失败，正在移除引用。</td></tr><tr><td>🟢 <code>更新</code> </td><td><code>已移除 [{backfill}]</code></td><td>回填引用已移除。若未停止，回填将自动替换。</td></tr><tr><td>🟡 <code>警告</code></td><td><code>移除失败 [{backfill}]</code></td><td>未找到回填引用，可能是重复调用。</td></tr></tbody></table>

[^1]: 数据传输对象

[^2]: [互联网服务提供商](https://en.wikipedia.org/wiki/Internet_service_provider)

[^3]: 最典型的是中国或俄罗斯
