> 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/ru/learn/podbor-igrokov/matchmaker-in-depth.md).

# Подробный обзор

Узнайте подробнее о no-code концепциях матчмейкера Edgegap и настройте их под свои нужды.

{% hint style="info" %}
Если вам нужна помощь, [свяжитесь с нами через Discord](https://discord.gg/MmJf8fWjnt). Для поддержки по играм в реальном времени см. нашу [систему тикетов](https://edgegap.atlassian.net/servicedesk/customer/portal/3).
{% endhint %}

## ✔️ Введение

Матчмейкинг в играх, основанных на матчах, как правило, стремится к следующему:

* **найти других игроков** на основе таких критериев, как регион, задержка, навыки или параметры игры;
* **найти серверы** чтобы подключиться к ним в зависимости от доступной вместимости \[или пинга, региона, навыков, карты, режима];
* **запустить новый сервер** если существующие серверы заполнены или не соответствуют критериям игрока.

Опыт игрока стоит на первом месте, определяя наши основные цели:

* высокая заполняемость матчей и интеграция социальных функций (игра с друзьями в группах),
* быстрые матчи с контролируемым качеством матчей (низкая задержка, общие предпочтения),
* надежный и предсказуемый процесс матчмейкинга с глобальной доступностью.

{% hint style="success" %}
В качестве альтернативы, позвольте игрокам **выбрать постоянный (всегда онлайн) сервер** из списка с [Браузер серверов](/ru/learn/brauzer-serverov.md).
{% endhint %}

**Начните менее чем за 5 минут и бесплатно протестируйте все функции — кредитная карта не требуется.**

Переходите на более мощный, приватный (выделенный) кластер, когда будете готовы. Нативная интеграция с Edgegap [Развертывания](/ru/learn/orkestraciya/deployments.md) обеспечивает лучший в классе пинг независимо от того, где находятся ваши игроки.

{% hint style="info" %}
Бесплатный тариф позволяет 3 часа работы после каждого перезапуска. Ваш матчмейкер будет работать на общей инфраструктуре с ограниченными ресурсами, подходящей для тестирования. **После публичного релиза вашему матчмейкеру нужно работать 24/7.**
{% endhint %}

Для каждого Matchmaker есть три основных понятия:

* [#hosting-cluster](#hosting-cluster "mention") - базовая серверная инфраструктура, полностью управляемая и обслуживаемая Edgegap.
* [#configuration](#configuration "mention") - набор правил и настроек, определяющих, как работает матчмейкер.
* 🌐 Экземпляр сервиса **-** живой сервис матчмейкинга, работающий 24/7 на кластере и использующий конфигурацию для сопоставления игроков и назначения развёртываний (серверов).

{% hint style="success" %}
[Часто обновляйте версию вашего матчмейкера](#changelog) чтобы **получать преимущества новых функций и исправлений ошибок.**
{% endhint %}

## ▶️ Начать матчмейкинг

**Быстро начните — добавьте наш стартовый SDK-образец в вашу игру**:

* Unreal Engine [Инструменты разработчика](/ru/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) (бесплатно для личного использования),
  * [импортировать простой пример blueprint](https://blueprintue.com/blueprint/m33u1okj/) (сопоставление игроков) и настроить под свои нужды.
* Unity [Инструменты разработчика](/ru/unity/developer-tools.md#software-development-kit):
  * [установите пакет бесплатно с помощью Unity Package Manager](https://github.com/edgegap/edgegap-unity-sdk),
  * [изучите наше руководство для начала работы и полные примеры](/ru/unity/podbor-igrokov.md).

Изучите процесс матчмейкинга, чтобы настраивать, устранять неполадки и оптимизировать интеграцию вашей игры:

<figure><img src="/files/de8d63bab346f3b338118bf18ccbe1eebd021d87" 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-заголовок с вашим секретом **Auth Token:**

<pre><code>Authorization: <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" %}
**Этот токен можно безопасно включить в ваш игровой клиент, так как он не даёт доступа к API Edgegap.**
{% endhint %}

Отдельных игроков можно идентифицировать по их 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/a7d88fc4e7173bede5ae8a8fb24d8cb577d4f854" alt=""><figcaption><p>Диаграмма жизненного цикла группы</p></figcaption></figure>

#### Лобби и группа

Используйте сервис лобби, если дизайн вашей игры требует настройки предпочтений для матчмейкинга, задаваемых игроком (например, выбор персонажа, сложность, карта и т. д.). По мере того как игроки входят в лобби и выходят из него, они также обновляют группу матчмейкинга, чтобы позже подготовиться к поиску матча.

{% hint style="success" %}
**Нет времени на сервис лобби?** Попросите игроков обмениваться ID группы через Discord или личные сообщения.
{% 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>хранить и управлять пользовательскими данными key-value</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">ПК</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) все участники группы отправляют свои [Пинг-маяки](/ru/learn/orkestraciya/ping-beacons.md) измерения в **чтобы не подбирать игроков из удалённых регионов** или с гораздо более высоким/низким пингом (латентностью).

{% code title="Пример измерений пинга игрового клиента в миллисекундах" %}

```json
{
  "Chicago": 224.4,
  "Frankfurt": 23.2,
  "Tokyo": 167.4
}
```

{% endcode %}

#### **Покинуть очередь**

Владелец группы может удалить группу, автоматически удалив все членства группы. Удаление группы после начала матчмейкинга отменит все членства и удалит их вскоре после этого.

Участники группы (кроме владельца) могут удалить свои членства (покинуть группу) в любое время до [#find-match](#find-match "mention"). Удаление членства после этого отменит матчмейкинг для всей группы.

{% hint style="info" %}
После отмены матчмейкинга участники [автоматически удаляются из матчмейкинга](#matchmaking-profiles) и получают уведомление через статус членства `status:CANCELLED`  в следующем ответе опроса статуса.
{% endhint %}

После отмены, если группа хочет перезапустить матчмейкинг, владелец группы должен заново создать группу, поделиться новым ID группы с участниками и заставить их заново создать свои членства.

**После того как матч найден, группу нельзя удалить** (`409 Conflict`), и она будет [удалена автоматически](#connect-to-server). Ваш сервер должен оставить игрокам некоторое время (например, 60 с) для подключения, прежде чем считать игрока покинувшим матч.

Если ваш сервер помечает игрока как покинувшего, вы можете:

* заменить ушедшего игрока ИИ-персонажем, чтобы немедленно начать матч,
* или создать [backfill](#backfill-match) чтобы найти нового игрока на замену ушедшему,
* или продолжить без замены ушедшего игрока, если дизайн вашей игры допускает переменное число игроков.

### Найти матч

Чтобы начать поиск матча, все участники и владелец должны пометить себя как готовых.

{% hint style="success" %}
Чтобы позволить владельцу группы **немедленно начать матчмейкинг, пометьте членства как готовые при создании**. Как только владелец пометит себя как готового, матчмейкинг начнётся, поскольку все готовы.
{% endhint %}

{% hint style="info" %}
Для лучшего опыта, **предоставляйте игрокам обновления статуса через внутриигровой интерфейс**.
{% endhint %}

**Все игроки должны опрашивать своё членство через регулярные интервалы** (рекомендуется 3–5 с), чтобы определить, когда начинается матчмейкинг, и сообщать о его прогрессе через внутриигровой интерфейс.

Игрокам следует **сохранять своё членство и ID группы в постоянном хранилище**, что позволяет им перезапустить игру и продолжить без потери прогресса матчмейкинга в случае сбоя игрового клиента.

Как только мы найдём достаточно игроков, чтобы собрать их в одну команду, соблюдая ваш [#matchmaking-rules](#matchmaking-rules "mention"), игроки будут уведомлены в ответе членства с `status:TEAM_FOUND`.

Удаление членства на этом этапе приведёт к отмене всех членств группы, а все остальные группы, назначенные в ту же команду, вернутся в `status:SEARCHING` .

Команды продолжают матчмейкинг с другими командами, используя пересекающиеся значения в своих группах (или среднее значение в случае `number_difference` ), пока не будет собрано достаточно команд. Членства указывают это в ответе  `status:MATCH_FOUND` , что означает, что ваш [развёртывание запускается](https://docs.edgegap.com/ru/learn/podbor-igrokov/pages/4ad5d792bc82dceeaec6d7dd56165ae188da0417#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" %}
Каждый игрок получает **уникальный Ticket ID, который можно использовать для** [#authenticate](#authenticate "mention") **с игровыми серверами.**
{% endhint %}

Если игрок был подобран и назначен на игровой сервер, его тикет удаляется автоматически. Игроки, покинувшие очередь после `status:HOST_ASSIGNED`  могут быть заменены [backfill](#backfill-match).

Как только игроки получают `status:HOST_ASSIGNED`  они переходят к [#connect-to-server](#connect-to-server "mention").

### Подключиться к серверу

Через несколько секунд после нахождения совпадения участники переходят к `status:HOST_ASSIGNED`  что означает, что ваш [развертывание уже готово, а ваш игровой сервер инициализируется](https://docs.edgegap.com/ru/learn/podbor-igrokov/pages/4ad5d792bc82dceeaec6d7dd56165ae188da0417#id-3.-deployment-ready).

Каждый игрок читает свой `ticket_id`  и  `назначение`  и пытаются подключиться, используя [**FQDN**](#user-content-fn-3)[^3] **(URL развертывания)** и **внешний порт**. В этот момент ваш игровой сервер может все еще инициализироваться, поэтому **игрокам нужно повторять попытку подключения несколько раз**, пока не будет превышено обычное время инициализации сервера:

{% tabs %}
{% tab title="Unreal Engine" %}
Чтобы **подключение из PIE (редактора)** во время разработки и тестирования нажмите клавишу тильды `~`  и введите `open {URL}:{port}`  и дождитесь, пока редактор загрузит карту.

Чтобы **подключение из сборки игрового клиента** (и в рабочей production-среде) попробуйте

* Unreal Engine [⚡ Integration Kit](https://docs.edgegap.com/learn/unreal-engine-games/developer-tools#integration-kit):
  * [установить из Fab Marketplace](https://www.fab.com/listings/ff17ad88-12a1-49cf-9a41-31695ed11e16) (бесплатно для личного использования),
  * [импортировать простой пример blueprint](https://blueprintue.com/blueprint/m33u1okj/) и настроить под свои нужды.

{% hint style="success" %}
В случае неудачного подключения или черного экрана обратитесь к нашему [руководству по устранению неполадок](/ru/unreal-engine.md#troubleshooting-and-faq).
{% endhint %}
{% endtab %}

{% tab title="Unity" %}
Чтобы **подключите ваш Unity Editor** или **игровой клиент** к вашему облачному развертыванию, укажите:

* **Развертывание** **URL** указывающий на IP-адрес сервера, обычно в `NetworkManager` компоненте.
* **внешний порт** сопоставленный с [внутренним портом прослушивания сервера](/ru/learn/orkestraciya/application-and-versions.md#port-mapping), обычно в компоненте Transport.

{% hint style="success" %}
В случае тайм-аута подключения или других проблем обратитесь к нашему [руководству по устранению неполадок](/ru/unity.md#troubleshooting-and-faq-4).
{% endhint %}
{% endtab %}
{% endtabs %}

{% hint style="info" %}
Мы не просим игроков подтверждать матч, поскольку стремимся обеспечить как можно более короткое время до начала игры, высокий процент заполнения матчей и минимизировать уклонение от очереди и отмены матчей.
{% endhint %}

Игровые клиенты должны **сохранять свой ID назначения в постоянном хранилище между перезапусками игры**, чтобы в случае сбоя игрового клиента они могли получить данные подключения и попытаться переподключиться.

### Матч для заполнения

При необходимости у некоторых игр могут быть особые требования к подбору игроков, например:

* позволять новым игрокам присоединяться к уже идущим играм (друзья или «рандомы»),
* заменять игроков, покидающих игру (ливеров) после запуска сервера, чтобы не перезапускать матч,
* позволять зрителям присоединяться и наблюдать за турниром или матчами друзей (киберспорт),
* собирать игроков на более крупных серверах, чтобы обеспечить больше социальных взаимодействий (MMO).

Backfill — это **серверный тикет, представляющий игроков, которые сейчас подключены к серверу.** Это гарантирует, что вновь добавленные игроки будут соблюдать ваши правила подбора при сопоставлении с текущими игроками.

{% hint style="warning" %}
[Подробный обзор](/ru/learn/podbor-igrokov/matchmaker-in-depth.md#backfill-match) для замены сессий Seat/Match. Matchmaker поддерживает только сессию Default.
{% endhint %}

<figure><img src="/files/39d6a1014be11c05325f3f774ba8a221dd36281b" alt=""><figcaption><p>Визуализация сценариев Backfill</p></figcaption></figure>

{% hint style="success" %}
**Backfill игнорируют** `player_count`  **правило и всегда сопоставляют ровно одну группу**. `backfill_group_size`  управляет вместимостью команды по стратегии round-robin, равномерно заполняя команды контролируемым образом.
{% endhint %}

**Чтобы успешно выполнить backfill, нужно:**

1. Сервер создаёт один Backfill для каждой команды, которой не хватает игроков, используя значения из:
   * Реальные `назначение`  данные, полученные из [Развертывания](/ru/learn/orkestraciya/deployments.md#injected-environment-variables) (развёртывания).
   * Текущих подключённых игроков' `тикеты`:
     * из [Подробный обзор](/ru/learn/podbor-igrokov/matchmaker-in-depth.md#injected-variables) (matchmaker), предыдущих backfill' `assigned_ticket` ответа или тестовых данных, изменённых для соответствия конкретным игрокам,
     * замените `backfill_group_size`  значения на возможные размеры групп [до доступной вместимости](#user-content-fn-4)[^4],
2. Игровые клиенты создают новые тикеты (участия) и включают `backfill_group_size`  значения:
   * `"1"`  если игрок подбирается в матч в одиночку.
   * [`"2"`  если игрок является частью группы подбора с 2x участниками всего](#user-content-fn-5)[^5].
   * `"new"`  если игроки разрешили запуск новых игр в дополнение к присоединению к уже идущим играм.
3. Игровые клиенты переходят к [Подробный обзор](/ru/learn/podbor-igrokov/matchmaker-in-depth.md#find-match) и сопоставляют игроков с соответствующим backfill.
4. Если группа, пополненная через backfill, не полностью заполнила команду, сервер может повторить этот процесс с тикетами новых игроков, добавленных через backfill, чтобы добавить ещё игроков и достичь нужного размера команды.

{% hint style="success" %}
Backfill игнорируют правила размера команды и всегда сопоставляют 1× backfill с 1× группой. **Чтобы сопоставлять только с backfill и отключить подбор с другими игроками в очереди, установите `min_team_size: 999999` .**
{% endhint %}

<details>

<summary>🥛 Пример Backfill (демонстрация Backfill)</summary>

```json
{
  "profile": "backfill-example",
  "attributes": {
    "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",
      "attributes": {
        "beacons": {
          "Нью-Йорк": 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",
      "attributes": {
        "beacons": {
          "Нью-Йорк": 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>🥛 Пример назначения Backfill (демонстрация Backfill)</summary>

```json
{
  "profile": "backfill-example",
  "attributes": {
    "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",
      "attributes": {
        "beacons": {
          "Нью-Йорк": 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",
      "attributes": {
        "beacons": {
          "Нью-Йорк": 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",
    "attributes": {
      "beacons": {
        "Нью-Йорк": 30.2,
        "Лос-Анджелес": 10.5,
        "Париж": 123.9
      },
      "backfill_group_size": [
        "new",
        "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 Seat](https://docs.edgegap.com/docs/sample-projects/mirror-on-edgegap#bonus-seat-sessions-management) и [Управление местами FishNet Seat](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. Создавайте новые Backfill для неиспользуемой ёмкости игроков (ушедших) на протяжении всего времени жизни сервера.
  3. Обновляйте просроченные Backfill, которые удаляются после `ticket_expiration_period`.
* **Очищайте (удаляйте) все оставшиеся Backfill** когда [/pages/4ad5d792bc82dceeaec6d7dd56165ae188da0417#id-5.-deployment-stopped](https://docs.edgegap.com/ru/learn/podbor-igrokov/pages/4ad5d792bc82dceeaec6d7dd56165ae188da0417#id-5.-deployment-stopped "mention"):
  * Unity - [`OnApplicationQuit`](https://docs.unity3d.com/6000.0/Documentation/ScriptReference/MonoBehaviour.OnApplicationQuit.html) callback или пользовательский callback завершения игры,
  * 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) , или пользовательский callback завершения игры.

{% hint style="info" %}
Используйте [GetEnvironmentVariable в C#](https://learn.microsoft.com/en-us/dotnet/api/system.environment.getenvironmentvariable?view=net-8.0) или [GetEnvironmentVariable в C++](https://dev.epicgames.com/documentation/en-us/unreal-engine/API/Runtime/Core/GenericPlatform/FGenericPlatformMisc/GetEnvironmentVariable) чтобы получить значения переменных.
{% endhint %}

Для Backfill можно использовать любой профиль, если указано действительное назначение сервера и предоставлен хотя бы один тикет. См. [Подбор игроков](/ru/learn/podbor-igrokov.md#backfill-showcase) минимальный пример.

## ⚙️ Конфигурация

API матчмейкера генерируется из JSON-конфигурации, заданной при создании нового (или при быстром перезапуске) Matchmaker. Вы можете указать любое количество профилей с различными правилами и расширениями:

{% hint style="success" %}
См. [Подбор игроков](/ru/learn/podbor-igrokov.md) наши SDK и подробные примерные сценарии.
{% endhint %}

<details>

<summary>🍀 Простой пример (минимальная рекомендуемая конфигурация)</summary>

<pre class="language-json"><code class="lang-json">{
  "version": "3.2.5",
  "inspect": true,
  "max_deployment_retry_count": 3,
  "profiles": {
    "simple-example": {
      "ticket_expiration_period": "5m",
      "ticket_removal_period": "1m",
      "group_inactivity_removal_period": "5m",
      "application": {
        "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>"
      },
      "rules": {
        "initial": {
          "match_size": {
            "type": "player_count",
            "attributes": {
              "team_count": 1,
              "min_team_size": 2,
              "max_team_size": 2
            }
          },
          "beacons": {
            "type": "latencies",
            "attributes": {
              "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> Пример конфигурации Backfill</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
{
  "version": "3.2.5",
  "inspect": true,
  "max_deployment_retry_count": 3,
  "profiles": {
    "cooperative-example": {
      "ticket_expiration_period": "3m",
      "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": 150
            }
          },
          "selected_difficulty": {
            "type": "string_equality"
          },
          "selected_map": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          },
          "player_level": {
            "type": "number_difference",
            "attributes": {
              "max_difference": 10
            }
          },
          "backfill_group_size": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          },
          "moderation_flags": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          }
        },
        "expansions": {
          "30": {
            "beacons": {
              "difference": 125,
              "max_latency": 250
            },
            "player_level": {
              "max_difference": 20
            }
          },
          "60": {
            "match_size": {
              "team_count": 1,
              "min_team_size": 2,
              "max_team_size": 4
            }
          },
          "150": {
            "match_size": {
              "team_count": 1,
              "min_team_size": 1,
              "max_team_size": 4
            }
          }
        }
      }
    }
  }
}
```

</details>

<details>

<summary>🎈 Пример социальной игры</summary>

```json
{
  "version": "3.2.5",
  "inspect": true,
  "max_deployment_retry_count": 3,
  "profiles": {
    "social-example": {
      "ticket_expiration_period": "3m",
      "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": {
            "attributes": {
              "team_count": 1,
              "min_team_size": 50,
              "max_team_size": 50
            },
            "type": "player_count"
          },
          "beacons": {
            "attributes": {
              "difference": 125,
              "max_latency": 150
            },
            "type": "latencies"
          },
          "selected_mode": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          },
          "backfill_group_size": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          },
          "moderation_flags": {
            "type": "intersection",
            "attributes": {
              "overlap": 1
            }
          }
        },
        "expansions": {
          "15": {
            "beacons": {
              "difference": 125,
              "max_latency": 250
            },
            "match_size": {
              "team_count": 1,
              "min_team_size": 20,
              "max_team_size": 50
            }
          },
          "30": {
            "match_size": {
              "team_count": 1,
              "min_team_size": 10,
              "max_team_size": 50
            }
          },
          "150": {
            "match_size": {
              "team_count": 1,
              "min_team_size": 1,
              "max_team_size": 50
            }
          }
        }
      }
    }
  }
}
```

</details>

{% hint style="warning" %}
Редактирование работающего матчмейкера **вызовет быструю перезагрузку**, удалив все тикеты и вызвав короткий простой.
{% endhint %}

<details>

<summary><code>Конфигурация приложения недействительна для профиля XYZ.</code></summary>

* Мы не смогли найти ваш [Приложения и версии](/ru/learn/orkestraciya/application-and-versions.md), пожалуйста, проверьте `приложение`  значения.

</details>

<details>

<summary><code>Docker-образ для '2024.01.30-16.23.00-UTC' не кэширован.</code></summary>

[**🌟 Обновитесь до тарифа Pay as You Go**](https://app.edgegap.com/user-settings?tab=memberships) **чтобы разблокировать** [**мгновенные развёртывания с кэшированием**](https://docs.edgegap.com/ru/learn/podbor-igrokov/pages/4ad5d792bc82dceeaec6d7dd56165ae188da0417#id-1.-start-a-deployment)**.**

* Некэшированные образы размером 4 ГБ и более могут дольше развёртываться, что приведёт к [/pages/4ad5d792bc82dceeaec6d7dd56165ae188da0417#id-4.-deployment-error](https://docs.edgegap.com/ru/learn/podbor-igrokov/pages/4ad5d792bc82dceeaec6d7dd56165ae188da0417#id-4.-deployment-error "mention"). Рассмотрите возможность оптимизации размера образа сервера ([Unreal Engine](/ru/unreal-engine.md#optimize-server-build-size) / [Unity](/ru/unity.md#optimize-server-build-size)).
* Вы всё равно можете продолжить, хотя мы рекомендуем протестировать время развёртывания.

</details>

### Профили (очереди) <a href="#matchmaking-profiles" id="matchmaking-profiles"></a>

Профили представляют собой полностью отдельные очереди матчмейкинга, использующие одну и ту же версию матчмейкера. Вы можете **настроить любое количество профилей для каждого матчмейкера.** Разделение базы игроков на несколько профилей может привести к более долгому времени ожидания в очереди для ваших игроков.

Каждый профиль матчмейкера использует [версию приложения](/ru/learn/orkestraciya/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) (или истечения), если возможен частичный матч (≥ min и < max размера команды), этот матч будет создан со всеми игроками на одной и той же стадии расширения (при условии прохождения других правил).

{% hint style="success" %}
Для кооперативных, free-for-all или асимметричных режимов с разным размером команды установите `"team_count": 1` .
{% endhint %}

Количество команд можно настроить так, чтобы собирать несколько сбалансированных команд для соревновательных игр:

* **атрибуты группы рассчитываются как среднее/пересечение** атрибутов игроков **группы,**
* **атрибуты команды рассчитываются как среднее/пересечение** атрибутов **группы команды.**

Предположим фиксированный размер команды в 4 игрока:

<figure><img src="/files/e5d57871dc252856b075a22e9725c5690d66f797" 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 никогда не совпадут.

| "Free For All" | "Capture The Flag" | "capture the flag" |
| -------------- | ------------------ | ------------------ |
| Alice          | Erin               | Frank              |
| Bob            | Charlie            |                    |
| Dave           |                    |                    |

</details>

**`number_difference`** подбирает игроков, если абсолютная числовая разница между ними находится в допустимых пределах.

<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/81d958edea12e340b96198f11c556ca754587237" alt=""><figcaption></figcaption></figure>

</details>

**`задержки`** — это специальное правило, оптимизирующее пинг матчей игроков:

* уменьшить задержку между клиентом и сервером, удаляя регионы с высокой задержкой (выше порога),
* повысить справедливость матчей, группируя игроков с похожей задержкой (ниже разницы).

<details>

<summary>Пример правила: <code>маяки</code></summary>

`маяки` правило, настроенное с `"difference": 100, "max_latency": 200`  будет сопоставлять:

:white\_check\_mark: Алиса и Боб могут быть сопоставлены:

* Токио отбрасывается (>200 мс),
* задержка для Чикаго в пределах абсолютной разницы 100 мс.

<table><thead><tr><th width="180">Город маяка</th><th width="80">Матч</th><th width="132">abs(A - B) [мс]</th><th width="164">Алиса [мс]</th><th width="164">Боб [мс]</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: Алиса и Чарли никогда не будут сопоставлены:

* нет маяков с задержкой < 200 мс для обоих игроков,
* Алиса живет в Северной Америке — Иллинойс,
* Чарли живет в Азии — Япония.

<table><thead><tr><th width="180">Город маяка</th><th width="80">Матч</th><th width="132">abs(A - B) [мс]</th><th width="164">Алиса [мс]</th><th width="164">Чарли [мс]</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] проблем или медленного соединения (например, беспроводного/мобильного) могут вызывать лаги и ухудшать игровой опыт других. Чтобы смягчить эту проблему:

* Постепенно расширяйте максимально допустимую задержку и разницу (см. [Пример расширенной конфигурации](/ru/learn/podbor-igrokov.md#advanced-example)),
  * игрокам с высоким пингом, возможно, придется ждать дольше обычного, чтобы найти матч.
* В качестве альтернативы разрешите игрокам переопределять измерение вручную, выбирая регион, и отправляйте поддельные значения пинга только для выбранных игроком регионов (например, 25 мс для быстрого матча),
  * это может отрицательно повлиять на опыт игры товарищей по команде и соперников.

{% hint style="info" %}
**Высокий пинг до маяка не всегда приводит к высокому пингу до сервера**. Развертывания доступны в большем количестве локаций, чем маяки. Маяки оркеструются в реальном времени для приоритизации глобального покрытия и надежности.
{% endhint %}

{% hint style="success" %}
См. [Подбор игроков](/ru/learn/podbor-igrokov.md) для **автоматизированное измерение пинга с помощью наших SDK**.
{% endhint %}

{% hint style="danger" %}
Маяки автоматически масштабируются в реальном времени — добавляются/удаляются/заменяются существующие маяки. Ваши клиенты и бэкенд должны учитывать это и **перезагружать список маяков перед каждым раундом подбора игроков**.
{% endhint %}

**`пересечение`** подбирает игроков с одним или несколькими совпадающими строковыми значениями с учётом регистра.

<details>

<summary>Пример правила: <code>selected_map</code></summary>

`selected_map` правило выше с `"overlap": 1`  будет подбирать:

:white\_check\_mark: Alice + Bob + Charlie могут совпасть, или Alice + Bob + Dave могут совпасть,

:x: Alice + Bob + Charlie + Dave никогда не совпадут.

<figure><img src="/files/583a8d57c0bcaf33a76b960c00485e98a69c6acd" alt=""><figcaption></figcaption></figure>

</details>

#### Расширение правил

При желании, **`расширения`**  изменяют атрибуты правила после определённого времени ожидания в очереди, чтобы ослабить ограничения и расширить пул игроков, которых можно подобрать, **что приводит к более быстрым матчам**.

<details>

<summary>Пример сценария: расширения</summary>

[Изначально нам нужна 1 команда, состоящая ровно из 4 игроков (возможно, разделённых на группы)](/ru/learn/podbor-igrokov.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 %}

## 📌 Внедряемые переменные

Вашему серверу может потребоваться знать детали о своих игроках. Атрибуты игрока, вычисленные значения матча и другие значения внедряются в ваше развертывание вместе с обычными [Приложения и версии](/ru/learn/orkestraciya/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 заявок игроков** чтобы вы могли легко [Развертывания](/ru/learn/orkestraciya/deployments.md#filter-deployments) и найти [Развертывания](/ru/learn/orkestraciya/deployments.md#container-logs) чтобы помочь вам устранить неполадки.

{% hint style="success" %}
**Отображайте ID заявок и ID развертываний в интерфейсе истории матчей клиента** чтобы отслеживать игроков при устранении неполадок.
{% endhint %}

{% hint style="info" %}
См. [Развертывания](/ru/learn/orkestraciya/deployments.md#connection-quality) чтобы узнать об устранении неполадок развертывания.
{% endhint %}

## 👀 Аналитика

Получайте представление о нагрузке и производительности вашего матчмейкера без кода и настройки.

🌟 [**Обновите Matchmaker до уровня Enterprise**](https://app.edgegap.com/matchmaker-management-v2/matchmakers/list) **чтобы открыть метрики и аналитику подбора игр:**

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

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

## ☁️ Кластер хостинга

Matchmaker удобно размещается и управляется Edgegap круглосуточно, 24/7.

Выберите вариант хостинга, лучше всего подходящий для вашей цели:

* **Бесплатный кластер (общий)** чтобы протестировать все функции и исследовать синергии с вашим дизайном,
  * автоматически отключается через 3 часа, для продолжения тестирования требуется перезапуск.
* **Приватный кластер** **(выделенный)** чтобы обеспечить стабильную среду для ваших производственных нужд,
  * выберите ваш регион и получите круглосуточную поддержку живых игр для выпуска с уверенностью.

#### Уровни частного кластера

В настоящее время мы предлагаем [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 + 2 ГБ ОЗУ</td><td align="right">6 vCPU + 12 ГБ ОЗУ</td><td align="right">18 vCPU + 48 ГБ ОЗУ</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, с круглосуточной живой поддержкой для публично выпущенных игр.

Требования к ресурсам вашего экземпляра будут зависеть от факторов:

* **количество игроков** - больше игроков приводит к большему числу заявок и API-запросов,
* **количество запросов на игрока** - более частые повторные попытки увеличивают нагрузку на сервис и расходуют ресурсы,
* **сложность конфигурации** - правила пересечения и расширения особенно ресурсоёмки,
* **средняя продолжительность матча** - более короткие сессии заставляют игроков чаще заново входить в подбор игр,
* **периоды истечения и удаления** - устаревшие заявки накапливаются со временем и потребляют ресурсы,
* **логика резервного повторного запроса клиента** - повторные попытки с джиттерным экспоненциальным backoff помогают распределить пики всплесков трафика.

{% hint style="warning" %}
**Подготовьтесь к успеху и оптимизируйте после запуска, чтобы не блокировать игроков в день релиза.** Используйте [Инструменты разработчика](/ru/unity/developer-tools.md#matchmaking-sdk) или **реализуйте экспоненциальный backoff с джиттером** чтобы восстановиться после высокой нагрузки.
{% endhint %}

{% hint style="info" %}
Наши кластеры используют облачные машины с процессорами AMD/Intel с тактовой частотой 2,4 - 3,2 ГГц.
{% endhint %}

## ⏩ Скользящие обновления <a href="#rolling-updates-and-ab-tests" id="rolling-updates-and-ab-tests"></a>

Отслеживание совместимости между версиями сервера и клиента может быть сложным. Следуйте нашим советам по надёжным релизам, обновлениям и предотвращению простоя или проблем совместимости.

**URL вашего Matchmaker и токен аутентификации всегда останутся прежними после перезапуска.**

{% hint style="danger" %}
**Создавайте отдельные matchmaker для разработки и производства** среды, чтобы безопасно экспериментировать.
{% endhint %}

#### ⚠️ **Перед выходом в продакшен**

Мы рекомендуем заранее создать несколько копий вашего matchmaker: `зелёный`, `синий` и `оранжевый`. Вы можете переключать используемый matchmaker по мере выпуска обновлений ([стратегия blue/green](https://en.wikipedia.org/wiki/Blue%E2%80%93green_deployment)).

**Выберите разные регионы для каждого экземпляра, чтобы предотвратить простой** во время локальных сбоев.

<figure><img src="/files/d133d707f5f79ffc15ab4244a9d943c30aa3f0b2" alt=""><figcaption><p>Пример среды DevOps Blue/Green</p></figcaption></figure>

#### **🔃 Обновление клиента + сервера**

**Предварительные требования:** Этот раздел предполагает, что вы уже выполнили [#before-going-live](#before-going-live "mention").

Для того чтобы **выпустить обновления клиента игры + сервера**, вы можете:

1. Подготовить новую версию серверного приложения `v1.2.0-rc` в Edgegap:
   1. отправить новый image tag в ваш реестр контейнеров `t1.2.0`,
   2. создать новую версию приложения `v1.2.0-rc`,
2. Выполните любые тесты разработки, [развернув новую версию приложения](https://app.edgegap.com/deployment-management/deployments/list) `v1.2.0-rc`:
   1. подключив Editor вашего игрового движка к указанному 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 и токен Authorization в клиенте игры,
5. Проведите QA-тесты и финальные проверки вашего нового клиента игры `c2`:
   1. если вы найдёте и устраните какие-либо проблемы, повторите процесс с начала,
   2. подождите 3–7 дней, чтобы изменения DNS matchmaker распространились у провайдеров по всему миру, после того как matchmaker был остановлен (быстрый перезапуск не требует обновлений DNS или периода ожидания),
6. Выпустите обновление нового клиента игры `c2` на платформах распространения игр,
7. Дайте время новому клиенту игры `c2` распространиться на устройства игроков (обычно до 3–7 дней):
   1. отслеживать устаревшие клиенты игры `c1`  используя развертывание [Развертывания](/ru/learn/orkestraciya/deployments.md#analytics),
8. Очистите неиспользуемые ресурсы в вашей учётной записи Edgegap:
   1. удалите image tag `t1.0.0` чтобы освободить место в Container Registry,
   2. удалите image tag `t1.1.0` чтобы освободить место в Container Registry,
   3. отключите ваш `зелёный`  matchmaker, чтобы приостановить биллинг до вашего следующего обновления.

{% hint style="success" %}
**Для вашего следующего обновления**, увеличьте номера версий и замените `зелёный` и `синий` ключевые слова в руководстве.
{% endhint %}

#### **⚡ Срочный серверный патч**

**Предварительные требования:** Этот раздел предполагает, что вы уже выполнили [#before-going-live](#before-going-live "mention").

Чтобы **выпустить патч сервера без необходимости обновления клиента игры**, вы можете:

1. Подготовить новую версию серверного приложения `v1.2.0-rc` в Edgegap:
   1. отправить новый image tag в ваш реестр контейнеров `t1.2.0`,
   2. создать новую версию приложения `v1.2.0-rc`,
2. Выполните тесты и проверки, [развернув новую версию приложения](https://app.edgegap.com/deployment-management/deployments/list) `v1.2.0-rc`:
   1. подключив Editor вашего игрового движка к указанному 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`  используя развертывание [Развертывания](/ru/learn/orkestraciya/deployments.md#analytics),
4. Очистка неиспользуемых ресурсов в вашей учётной записи Edgegap:
   1. удалите image tag `t1.1.0` чтобы освободить место в Container Registry.

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

Клиенты и серверы могут вызывать API напрямую или через SDK игровых движков, см. также [Подбор игроков](/ru/learn/podbor-igrokov.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 и удобный веб-интерфейс. Откройте URL в браузере, чтобы просмотреть и протестировать все конечные точки API и изучить примеры полезных нагрузок.
{% endhint %}

{% tabs fullWidth="false" %}
{% tab title="🍀 Простой пример" %}
{% file src="/files/7d0f90dc43c3b7d145adac1ad73250ee407bb816" %}
{% endtab %}

{% tab title="🏁 Продвинутый пример" %}
{% file src="/files/174cc4ac8b555f73c277175e8e15173e226b8ed9" %}
{% endtab %}

{% tab title="🎾 Пользовательский лобби" %}
{% file src="/files/11e2695177f3949632a909a5baf2c4d45c2ebfdc" %}
{% endtab %}

{% tab title="🥛 Демонстрация подбора игроков" %}
{% file src="/files/db149be8a4616a601a799ce1f015caace9ee1e03" %}
{% endtab %}

{% tab title="⚔️ Соревновательные игры" %}
{% file src="/files/4438d60914c9c7a4b475bb5bc172ebe487125bbd" %}
{% endtab %}

{% tab title="🤝 Кооперативные игры" %}
{% file src="/files/5794324ea05f7587619d5cc384394d352fb718d8" %}
{% endtab %}

{% tab title="🎈 Социальные игры" %}
{% file src="/files/17d42dcf1fc9846bdbb74a6d6303005d408f851e" %}
{% endtab %}
{% endtabs %}

Импортировать спецификацию API в [Веб-клиент Scalar API](https://client.scalar.com/workspace/default/request/default) или [Swagger Editor](https://editor.swagger.io/) для изучения деталей.

### Ограничения скорости

Чтобы защитить ваш кластер от превышения пиковой пропускной способности и сбоя, мы ограничиваем количество запросов в секунду на основе наших внутренних нагрузочных тестов, используя [Подбор игроков](/ru/learn/podbor-igrokov.md#advanced-example) конфигурацию.

<table><thead><tr><th>конечная точка API</th><th width="130">Бесплатный уровень</th><th width="130">Уровень Hobbyist</th><th width="130">Уровень Studio</th><th width="130">Уровень Enterprise</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>Создать backfill</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 в одну и ту же секунду.                          |
| ✅ Игроки ждут всё больше времени между повторными попытками (например, 1 с – 5 с – 10 с – 10 с).           | ❌ Все игроки повторяют попытку немедленно при получении `429 Слишком много запросов`  ответа.   |
| ✅ Большинство игроков получат свои назначения в течение короткого времени (10–60 с) и прекратят опрос.     | ❌ Все игроки продолжают опрашивать в течение заданного времени даже после получения назначения. |
| ✅ Большинство игроков завершают свою игру (это занимает время), прежде чем начать новую сессию.            | ❌ Все игроки немедленно перезапускают свою сессию сразу после получения назначения сервера.     |
| ✅ Пиковый трафик сохраняется примерно 6 часов в день, после чего часть часовых поясов отключается.         | ❌ Пиковый трафик сохраняется 24 часа в сутки, и все игроки играют и днём и ночью.               |

#### Поведение под нагрузкой

Если matchmaker испытывает высокую нагрузку:

* если процессор троттлит, подбор игр может замедлиться,
* если у matchmaker закончится память, он перезапустится без потери информации о заявках, рассчитывая, что клиенты реализуют экспоненциальный backoff и всплеск распределится на более длительный период времени.

#### Межсайтовый обмен ресурсами (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"
  ],
  "profiles": {
      <a data-footnote-ref href="#user-content-fn-11">...</a>
  }
}
</code></pre>

</details>

* или добавить в белый список домен с подстановочным знаком (включая все поддомены):

<details>

<summary>🍀 Простой пример (пример с wildcard-доменом)</summary>

<pre class="language-json"><code class="lang-json">{
  "version": "3.2.3",
  "allowed_cors_origins": ["https://*.my-game-server.com"],
  "profiles": {
      <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>

Добавьте расширенные или настраиваемые элементы управления потоком matchmaking — реализуйте собственный прокси с помощью нашего [Управляемые кластеры](/ru/learn/advanced-features/managed-clusters.md) или любого облачного FaaS[^12] вычислительного платформы, чтобы добиться любого из следующих:

* прикреплять конфиденциальные атрибуты игрока — такие как флаги читера, рейтинги навыка или подобное,
* предоставлять внутриигровой контекст команды и матча — показывать моих товарищей по команде и соперников во время загрузки,
* ограничивать конкретные крайние случаи — например, разрешать только 1 группу на игрока в любой момент времени,
* добавить кеширование или ограничение частоты API — уменьшить число запросов и нагрузку на matchmaker,
* настроить интеграцию lobby-group — создавать асимметричные/ролевые лобби перед matchmaking.

{% hint style="success" %}
**Включите параметр `player_ip`  с публичным IP-адресом участника** чтобы обеспечить минимально возможную задержку для игрока и воспользоваться [/pages/4ad5d792bc82dceeaec6d7dd56165ae188da0417#id-1.-server-score-strategy-best-practice](https://docs.edgegap.com/ru/learn/podbor-igrokov/pages/4ad5d792bc82dceeaec6d7dd56165ae188da0417#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/93040a08d96eb0a657bc04834091d9667fff7716" alt=""><figcaption><p>Диаграмма активности Server-to-Server Matchmaking</p></figcaption></figure>

## 🚨 Устранение неполадок

**Ваш успех — наш приоритет.** Если вы хотите отправить пользовательские запросы, попросить о недостающих критически важных функциях или поделиться любыми мыслями, [пожалуйста, свяжитесь с нами в нашем Community Discord](https://discord.gg/MmJf8fWjnt).

<details>

<summary><code>Конфигурация приложения недействительна для профиля XYZ.</code></summary>

* Мы не смогли найти ваш [Приложения и версии](/ru/learn/orkestraciya/application-and-versions.md), пожалуйста, проверьте `приложение`  значения.

</details>

<details>

<summary><code>Docker-образ для '2024.01.30-16.23.00-UTC' не кэширован.</code></summary>

[**🌟 Обновитесь до тарифа Pay as You Go**](https://app.edgegap.com/user-settings?tab=memberships) **чтобы разблокировать** [**мгновенные развёртывания с кэшированием**](https://docs.edgegap.com/ru/learn/podbor-igrokov/pages/4ad5d792bc82dceeaec6d7dd56165ae188da0417#id-1.-start-a-deployment)**.**

* Некэшированные образы размером 4 ГБ и более могут дольше развёртываться, что приведёт к [/pages/4ad5d792bc82dceeaec6d7dd56165ae188da0417#id-4.-deployment-error](https://docs.edgegap.com/ru/learn/podbor-igrokov/pages/4ad5d792bc82dceeaec6d7dd56165ae188da0417#id-4.-deployment-error "mention"). Рассмотрите возможность оптимизации размера образа сервера ([Unreal Engine](/ru/unreal-engine.md#optimize-server-build-size) / [Unity](/ru/unity.md#optimize-server-build-size)).
* Вы всё равно можете продолжить, хотя мы рекомендуем протестировать время развёртывания.

</details>

<details>

<summary>Почему я получаю ошибки при попытке создать новый matchmaker?</summary>

* Пожалуйста, прочитайте ошибку — возможно, вы неправильно написали идентификатор, правило или оператор. - Используйте [JSONLint](https://jsonlint.com/) чтобы проверить форматирование JSON; возможно, вы пропустили запятую или скобку. - Обратитесь через [наш Community 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>ПОИСК</code> .</summary>

* Пожалуйста, убедитесь, что вы создали достаточно совпадающих заявок в соответствии с вашей конфигурацией.

</details>

<details>

<summary>Моя заявка застряла, переключаясь между <code>MATCH_FOUND</code> и <code>КОМАНДА НАЙДЕНА</code> многократно.</summary>

* Учётные записи на бесплатном уровне ограничены 1 развертыванием одновременно.
* Пожалуйста, рассмотрите обновление или остановите текущее развертывание, чтобы запустить новое.

</details>

<details>

<summary>Моя заявка сразу переходит в <code>ОТМЕНЕНА</code>.</summary>

* Срок действия вашей заявки истёк. Создайте новую заявку или увеличьте период истечения в вашей конфигурации для тестирования.

</details>

<details>

<summary>Я получаю <code>HTTP 404 Не найдено</code> при проверке моей заявки.</summary>

* Ваша заявка была удалена либо запросом DELETE, либо по достижении периода удаления (начинается после истечения срока действия заявки и определяется в вашей конфигурации). Создайте новую заявку заново или увеличьте периоды истечения/удаления в вашей конфигурации для тестирования.

</details>

<details>

<summary>В моём matchmaker отображается ошибка, что мне делать?</summary>

* Если это экземпляр для разработки или тестирования, сначала попробуйте перезапустить ваш matchmaker. - Пожалуйста, сообщайте о любых проблемах через [наш Community Discord](https://discord.gg/MmJf8fWjnt).
* Если эта проблема влияет на живую игру, создайте [срочный запрос в поддержку](https://edgegap.atlassian.net/servicedesk/customer/portal/3).

</details>

## 🔖 Журнал изменений

#### Семантическое версионирование

Наши инструменты для разработчиков и управляемые сервисы используют официальное [Семантическое версионирование](https://semver.org/), что указывает, какие обновления ✅ безопасны (minor, patch), а какие могут содержать ⚠️ несовместимые изменения (major).

**После выпуска версия никогда не будет изменена**.

Ваш конфигурационный файл будет проверяться в зависимости от используемой версии matchmaker; убедитесь, что ваши правила соответствуют возможностям версии matchmaker.

{% hint style="info" %}
**Последняя версия matchmaker — `3.2.5`**. Все примеры на этой странице актуальны.

Следите за [обновлениями и объявлениями](/ru/docs/release-notes.md). См. также [#rolling-updates-and-ab-tests](#rolling-updates-and-ab-tests "mention").
{% endhint %}

{% hint style="warning" %}
**Чтобы обновить версию matchmaker — Stop, Edit, Restart.** Быстрый перезапуск не применит изменения версии.
{% endhint %}

[^1]: пример значения

[^2]: игровые клиенты присоединяются к лобби, чтобы получить ID группы матчмейкинга и присоединиться к группе

[^3]: Fully Qualified Domain Name

[^4]: например, для 3 свободных слотов = \["3", "2", "1"]

[^5]: замените "2" на число фактических участников группы

[^6]: замените на собственное имя приложения

[^7]: замените на собственную версию приложения

[^8]: превышена максимальная разница

[^9]: превышена максимальная задержка

[^10]: поставщик интернет-услуг

[^11]: см. другие примеры

[^12]: [Function as a Service](https://www.ibm.com/think/topics/faas)
