Эта страница ещё не переведена — показана английская версия.
PlayServ SDK
Игровой бэкенд, который идёт в комплекте с геймплеем. PlayServ — это бэкенд как сервис для игр-сервисов. Студия получает готовые данные, игроков, комнаты, подбор игроков и коммерцию и не держит для этого собственных серверов. SDK связывает с платформой ваш код — и серверный, и тот, что работает в движке.
Симуляцию пишете не вы
Комнаты, столкновения, перемещение, предсказание и синхронизация работают внутри платформы. Ваша игра состоит из четырёх частей:
- объявления (declaration) — сущности, карты, способности, таблицы выпадения, правила синхронизации;
- хуки — ваши правила, которые платформа вызывает на именованных шагах;
- события (event) — на них подписываются, а не опрашивают;
- операции (operation) — то, что вы запрашиваете или приказываете.
Каждая страница модуля устроена вокруг этих четырёх частей.
Писать не придётся вполне конкретные вещи: игровой цикл, сборку снапшотов, кодирование дельт, разрешение столкновений, интегрирование движения, обработку переподключений, проверку попаданий с компенсацией лагов. Игра уровня Tanks укладывается примерно в 300 строк — её шаг за шагом собирают на странице Первые шаги.
Изменили объявленное состояние — значит, отправили по сети
Отдельного в ызова отправки нет. Рядом с полем (field) вы одним атрибутом указываете, как оно синхронизируется, и дальше любое изменение поля само уходит по сети. Из этого объявления следует всё остальное: дельты от последнего подтверждённого состояния, политика для каждого аспекта, приоритет и частота отправки, окно хранения истории, хуки на изменение. Ничего из этого писать не нужно.
Так же устроено всё, что объявляется: событие, RPC, группа (group), ось таблицы лидеров (leaderboard). Из одного объявления получаются типизированный API в каждом биндинге, экран в админ-панели, именованные шаги, которые можно заменить своими хуками, правила доступа для каждого актора и сгенерированный код для каждого биндинга. Поэтому версионируют объявление, а не сгенерированный код. Подробнее — на страницах Data & Subscriptions и Схема в коде.
Интерфейсы зависят от актора, а не от стороны
Отдельных SDK для клиента и для сервера нет. SDK один, а что разрешено конкретному вызову, решает актор, от имени которого он сделан: игрок (player), сервис, мозг бота, опера тор.
Главный сценарий, под который это спроектировано, — машина игрока, которая сама создаёт комнату (room) и сама её ведёт. Такая машина — мастер-клиент: у неё есть интерфейсы владельца комнаты и ничего сверх того. В сборке room-visitor нельзя выгнать игрока или закрыть комнату: эти интерфейсы в неё просто не входят.
Права собираются из атомарных разрешений (permission), поэтому готовых уровней доступа нет, а роль (role) может ограничить доступ к данным вплоть до отдельной строки и столбца. См. Кто принимает решения, а как записываются выданные права (grant) — на странице Access & Roles.
Один дизайн, один стек
Как он написан
SDK — это единый дизайн, который сужается двумя способами, и ничто не опускается на уровень ниже, пока уровень выше может это выразить. Общие принципы одинаковы во всех биндингах. Особенности языка добавляют только то, что его парадигма не позволяет выразить общим способом. Особенности движка добавляют только то, что движок перестраивает поверх своего языка: в Unreal, например, объявление живёт внутри собственного макроса рефлексии.
Как он работает
Код игры обращается только к модулям. Модули собраны из четырёх примитивов: событий, RPC, данных с подписками и групп. Под ними работает хаб, который вы никогда не вызываете напрямую: внедрение зависимостей, монтирование модулей, сессия, восстановление состояния, качество доставки сообщений. Ещё ниже — транспортные адаптеры, по одному на протокол. Какой из них понесёт вызов, ваш код не выбирает и даже не замечает.
Обе части подробно описаны на странице Как устроен SDK и дальше, вплоть до Под капотом.
Модули складываются, а не наследуются
Базового модуля, от которого нужно наследоваться, нет, как нет и иерархии для расширения. Модули образуют граф, потому что реальные фичи пересекают ветки: модуль Matchmaking резервирует места (seat) в комнатах, выпавшие предметы появляются на карте (map), чат живёт внутри комнаты.
Под словом «наследование» здесь скрываются четыре ра зных механизма, и их стоит различать. RPC сущности (entity) — часть самой сущности. Пресет — именованный набор аспектов, а не базовый класс. Чтобы переопределить шаг платформы, достаточно поставить атрибут на свою замену. Один модуль заимствует другой через декоратор, который сужает заимствованный интерфейс. См. Наследование и композиция.
Кто что видит — решает объявление, а не фильтр на клиенте
На сорок игроков ещё можно рассылать снапшот всей комнаты, на двести — уже нет. Кто какую часть мира получает, решают правила зоны интереса (interest rules). Персональные пакеты для каждого актора и общая рассылка — два режима доставки одной объявленной модели, поэтому перейти с одного на другой можно настройкой, без переписывания кода. Далёкие объекты, прежде чем исчезнуть, постепенно упрощаются по объявленным уровням детализации (detail tier).
Заодно это вопрос безопасности: состояние, которое не должно утечь, просто не отправляется. Туман войны и поля, доступные только владельцу, отсутствуют в пакете, а не прячутся на клиенте. Зри тели, администраторы и повторы видят больше, потому что у них шире выданные права. См. Visibility.
Что остаётся после потери хоста
Если хост упал, матч на этом не заканчивается. Пока идёт игра, состояние комнаты не копируется между хостами: владелец один, и порядок действий держится без консенсуса. Матч выживает потому, что его состояние объявлено, а объявленное состояние хранится вне хоста: платформа делает его снапшот с объявленным интервалом. Новый хост продолжает с последнего снапшота.
При этом у нового хоста есть состояние только на момент снапшота, и всё, что произошло после, теряется. Деплой использует тот же механизм, но без потерь: вывести хост из работы (drain) — значит намеренно пройти тот же путь, что и при отказе.
Состояние, которое живёт только в движке, не восстанавливается
Если состояние хранится только в акторах движка, оно не объявлено, и у нового хоста его не будет. ::: Подробнее — на странице Что остаётся после потери хоста, а про льготный период, за который игрок может вернуться в матч, — на странице Rooms.
Любой шаг платформы можно заменить своим
Любой сценарий платформы — это цепочка зарегистрированных функций, и любое звено можно заменить или обернуть. Вход, проверка входа в комнату, покупка, отправка результата, загрузка файла — у каждого такого шага есть имя. Замена объявляется атрибутом: версию можно выбирать по условию, а собственный шаг платформы остаётся запасным вариантом.
Вместо того чтобы форкать исходники платформы, вы заменяете её шаги. См. Extensibility.
Один контракт, шесть языков
Контракт один, проекций шесть: C#, TypeScript, Python и Go на сервере, сгенерированные Unreal C++ и Unity C# в движке. Все примеры кода на сайте показаны на всех шести языках. Если в каком-то биндинге для шага нет интерфейса, вкладка объясняет почему: шаг выполняется вне движка или право на такой вызов есть у другого актора.
Перед выбором языка полезно знать две вещи. RPC принимает объекты SDK по ссылке, а не плоские DTO. Асинхронные примитивы встроены — каналы, потоки данных и адресация групп: можно обратиться ко всей группе сразу и собрать ответы или читать файл частями, пока он ещё загружается.
Есть и детерминированный хост в памяти. Он запускает код игры без бэкенда, а временем управляете вы, поэтому тесты воспроизводимы. См. Потоки, время жизни и тесты.
Чего в SDK намеренно нет — деплоя, биллинга, управления организациями и пользователями, — то находится на операторском уровне (operator plane). Всё остальное — в боковом меню, а быстрее всего начать со страницы Первые шаги.