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

# Матчмейкинг

Добавьте матчмейкинг в свою игру на Unity с помощью дополнительного стартового SDK Edgegap, готового к расширению и настройке по мере роста вашего многопользовательского проекта.

Этот SDK — необязательный стартовый набор для пользователей Unity, который можно будет расширять и настраивать позже.

## 💡 Функции

{% columns %}
{% column %}

* Полные примеры
* Автоматизация пинга
* Тикеты, группы, команды
  {% 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>

Git-клиент нужен, чтобы Unity могла автоматически загрузить и установить наш пакет Unity. После установки вам не потребуется напрямую использовать git.

</details>

#### Установка

1. Откройте свой проект Unity,
2. Выберите `Окно > Управление пакетами > Менеджер пакетов` ,
3. Нажмите на :heavy\_plus\_sign: значок и выберите `Добавить пакет из git URL...` ,
4. Когда появится запрос, введите URL нашего SDK:

{% code title="" %}

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

{% endcode %}

5. Нажмите `Добавить`  и дождитесь завершения установки.

#### Импортировать примеры

Этот пакет включает несколько примеров, предназначенных для использования по отдельности (не объединяйте примеры).

#### Проверенные источники

Это единственный официальный канал распространения этого SDK, не доверяйте непроверенным источникам!

#### Обновить пакет

Перейдите к Edgegap SDK в Unity Package Manager и нажмите `Обновить` .

{% hint style="warning" %}
**Импортированные примеры не обновляются автоматически!** Сделайте резервную копию всех пользовательских значений свойств, удалите текущие скрипты примеров, используемые в вашей сцене, и импортируйте примеры заново.
{% endhint %}

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

#### Обновление до v3

Это обновление включает множество новых [Браузер серверов](/ru/unity/server-browser.md) утилит и примеров, улучшает обработку ошибок matchmaking и многое другое. См. [Примечания к релизам](/ru/docs/release-notes.md) полный список.

{% hint style="warning" %}
Обновление Unity SDK v3 включает несколько критических изменений. Пожалуйста, тщательно повторно протестируйте вашу интеграцию.
{% endhint %}

## 🍀 Начало работы

Это руководство предполагает базовые знания [Матчмейкинг](/ru/learn/matchmeiking.md) концепций и работающий Matchmaker.

{% hint style="success" %}
**Мы настоятельно рекомендуем импортировать наш простой пример** чтобы следовать коду по мере чтения этого документа. Вы можете сделать это в `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" %}
Этот пакет объединяет оба [Браузер серверов](/ru/learn/brauzer-serverov.md) и [Матчмейкинг](/ru/learn/matchmeiking.md)которые можно использовать вместе или по отдельности. Вы можете свободно повторно использовать любые сценарии для своих собственных модифицированных форков и интеграций.
{% endhint %}

Этот пакет включает:

* Файлы времени выполнения — будут скомпилированы и включены в сборки клиента и сервера:
  * Утилиты, специфичные для сервиса:
    * [#client-agent](#client-agent "mention") - полная интеграция клиента для повторного использования/расширения.
    * Функции API — определения конечных точек, обработка ошибок и автоматизация логирования.
  * Специфичные для сервиса DTO[^1] - типизированные контейнеры данных для API матчмейкинга.
  * Общие утилиты — логирование, HTTP, пинг, наблюдаемые объекты и т. д...
  * Общие DTO[^1] - используются несколькими сервисами Edgegap для передачи данных.
* Файлы примеров — включаются и компилируются ТОЛЬКО если импортированы в ваш проект:
  * [#simple-example](#simple-example "mention") - примеры обработчиков для [минимальной конфигурации](/ru/learn/matchmeiking.md#simple-example).
  * [#region-picker](#region-picker "mention") - изучите интеграцию UI с ручным выбором региона.

### Клиент группы

**Автоматизация пинга, управление тикетами и получение хоста** выполняются Group Client.

После создания, агента **родительский Monobehaviour (обработчик) должен инициализировать клиент** и предоставить:

* `onMonitorUpdate`  обратный вызов — отслеживать изменения состояния сервиса.
* `onAssignmentUpdate`  обратный вызов — отслеживать и реагировать на изменения назначения хоста.

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

Обработчик клиента, как ожидается, возьмёт управление и вызовет функции клиента с этого момента:

* `Маяки`  для получения списка доступных [Пинг-маяки](/ru/learn/orkestraciya/ping-beacons.md).
* `MeasureBeaconsRoundTripTime`  для выполнения измерений пинга относительно заданного набора маяков.
* `CreateGroup`  для лидера лобби, чтобы создать группу с возможностью присоединения, в которую можно пригласить друзей.
* `JoinGroup`  чтобы присоединиться к существующей группе, используя ID группы, отправленный через сторонний лобби/бэкенд.
* `SetReady`  чтобы пометить владельца группы и участников как готовых и начать поиск матчей.
* `ResumeMatchmaking`  загрузить кэшированную группу и продолжить поиск в случае сбоя клиента.
* `StopMatchmaking`  чтобы удалить тикет (если матч не найден) и покинуть очередь.
* `Статус`  для проверки состояния сервиса Matchmaker.

Когда устанавливается новое подключение игрока, ожидается, что игрок отправит свой ID тикета на игровой сервер с помощью вашего netcode, чтобы сопоставить подключения с [Подробный обзор](/ru/learn/matchmeiking/matchmaker-in-depth.md#injected-variables).

{% hint style="success" %}
Сохраните сведения о подключении в клиенте или игровом бэкенде, чтобы переподключиться в случае неожиданного сбоя.
{% endhint %}

## Серверный агент

Серверный агент выполняет **создание backfill, обнаружение назначения тикетов, обнаружение отказа от backfill и его удаления. Он также отслеживает и воссоздаёт backfill'ы, срок действия которых истёк, у которых истёк период ожидания подключения или которые были брошены — чтобы достичь желаемого размера команды**.

Серверный агент отслеживает текущих подключённых игроков и автоматически включает их тикеты в новые backfill'ы, чтобы гарантировать, что игроки, добавленные через backfill, будут подбираться по правилам настроенного профиля.

После создания, агента **родительский Monobehaviour (обработчик) должен инициализировать клиент** и предоставить:

* `onMonitorUpdate`  обратный вызов — отслеживать изменения состояния сервиса.
* `onBackfillUpdate` обратный вызов — отслеживать изменения backfill и реагировать на них.

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

Ожидается, что обработчик сервера возьмёт управление и вызовет функции клиента с этого момента:

* `PlayerConnected`  чтобы не заменять первоначальных или добавленных через backfill игроков, которые так и не подключились.
* `AbandonPlayer`  чтобы сообщить, что подключённый игрок покинул сервер и его нужно заменить.
* `AbandonAllBackfills`  чтобы немедленно остановить заполнение сервера и удалить backfill'ы.
  * Этот метод следует вызвать перед остановкой сервера. Игроки, которые уже назначены на этот момент, должны повторно присоединиться к матчмейкингу, поскольку сервер завершается.
  * Назначенные на момент этого вызова backfill'ы всё ещё могут подключиться в пределах заданного периода ожидания.
* `AbandonBackfill`  чтобы принудительно отменить конкретный backfill (для пользовательских реализаций обработчика).
* `Статус`  для проверки состояния сервиса матчмейкера.

## 🧪 Примеры

Начните с примеров, включая полную рабочую интеграцию как для сервера, так и для клиента.

### Простой пример

Включает полную реализацию жизненного цикла игрока с измерением пинга, управлением тикетами и получением назначения хоста. Демонстрирует, как читать внедрённые переменные матча на стороне сервера.

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

### Выбор региона

У некоторых игроков (или групп) есть особые локальные условия (например, ISP[^2] блокировка, [общенациональная блокировка](#user-content-fn-3)[^3], или другие) и они могут предпочесть выбирать регион вручную, а не только на основе пинга.

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

### Собраться в группу

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

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

### Дозаполнение

Повторно используйте серверные ресурсы и добавляйте игроков в уже запущенные развертывания. Задайте целевой размер команды и дождитесь добавления игроков. Включает автоматический период ожидания подключения и воссоздание истёкших backfill'ов.

Настройте пример серверного обработчика для многокомандных или асимметричных составов команд.

## ⚙️ Настройка

Этот SDK предназначен для расширения и модификации, хотя некоторые изменения могут быть рискованными:

✅ Обработчик — безопасно подключайте наблюдателей UI и вносите небольшие дополнения или изменения,

⚠️ Агент — изменяйте управление жизненным циклом игрока на свой страх и риск,

⚠️ API — пишите собственную интеграцию с нуля, используя выбранные утилиты.

Обработчики могут наблюдать любые события, создаваемые агентами Server и Client, как описано ниже.

{% hint style="warning" %}
Убедитесь, что вы хорошо знакомы с [Матчмейкинг в деталях](/ru/learn/matchmeiking/matchmaker-in-depth.md) концепциями перед внесением изменений.
{% endhint %}

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

### События сервера

Серверный агент генерирует события (действия), которые родительский обработчик должен наблюдать и обрабатывать. Серверный агент, генерирующий эти события, инициализируется только в [#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>Backfill создан успешно.</td></tr><tr><td>🔴 <code>Ошибка</code></td><td><code>не удалось создать</code></td><td>Неожиданная проблема с backfill. Проверьте состояние сервиса.</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>Тикет успешно назначен backfill.</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>Не найдено, ссылка удаляется. Вероятнее всего, срок действия backfill истёк.</td></tr><tr><td>🔴 <code>Ошибка</code></td><td><code>не удалось опросить (достигнут максимум повторных попыток) [{backfill}]</code></td><td>Попытки исчерпаны, backfill отменяется.</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>Backfill отменён, ссылка удаляется.</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>Ссылка на backfill удалена. Backfill будет автоматически заменён, если его не остановить.</td></tr><tr><td>🟡 <code>Предупреждение</code></td><td><code>не удалось удалить [{backfill}]</code></td><td>Ссылка на backfill не найдена, вероятно, повторный вызов.</td></tr></tbody></table>

[^1]: Объект передачи данных

[^2]: [Поставщик интернет-услуг](https://en.wikipedia.org/wiki/Internet_service_provider)

[^3]: в частности в Китае или России
