Перейти до основного вмісту
З чого почати

Цю сторінку ще не перекладено — показано англійську версію.

PlayServ SDK

Ігровий бекенд, який постачається разом із геймплеєм. PlayServ — це бекенд як сервіс для live-ігор: студія отримує бекенд своєї гри — дані, гравців, кімнати, підбір гравців, комерцію — і не тримає для цього власних серверів. Через SDK ваш код — і серверний, і той, що працює в рушії, — взаємодіє з цією платформою.

Симуляцію пишете не ви

declarations — what exists and how it behavesoperations — what you ask forthe platform runs the room tickevents — what happenedhooks — your rules, at named stepslocomotioncollisiondata and syncprediction
Тік кімнати виконує платформа, а гра працює з нею чотирма способами

Кімнати, зіткнення, переміщення, передбачення й синхронізація працюють усередині платформи. Ваша гра складається з чотирьох частин:

  • оголошення (declaration) — сутності, мапи, здібності, таблиці випадання, правила синхронізації;
  • хуки — ваші правила, які платформа викликає на іменованих кроках;
  • події (event) — на них підписуються, а не опитують їх;
  • операції (operation) — те, що ви запитуєте або наказуєте зробити.

Кожна сторінка модуля побудована саме навколо цих чотирьох частин.

Ось що вам не доведеться писати: ігровий цикл, збирання снапшотів, дельта-кодувальник, розв’язання зіткнень, інтегрування руху, обробку перепідключень, перевірку влучань із компенсацією лагів. Гра на кшталт Tanks вміщується в ~300 рядків — її збирає сторінка Перші кроки.

Змінили оголошений стан — отже, відправили по мережі

Окремого відправлення немає. Ви задаєте, як синхронізується поле, одним атрибутом поруч із ним, і зміна поля — це і є мережева операція. Дельти відносно останнього підтвердженого стану, політика для кожного аспекту, пріоритет і частота відправлення, вікно зберігання (retained window) і хуки на зміни — усе це випливає з оголошення, і нічого з цього ви не пишете самі.

Те саме стосується всього іншого, що ви оголошуєте: події, RPC, групи, осі таблиці лідерів. Одне оголошення стає типізованим API в кожному біндингу, екраном в адмін-панелі, іменованими кроками, які можуть замінити ваші хуки, правилами доступу для кожного актора і згенерованим кодом для кожного біндингу. Саме тому ви версіонуєте оголошення, а не згенерований код. Див. Data & Subscriptions і Схема в коді.

Інтерфейси залежать від актора, а не від сторони

Окремих SDK для клієнта й для сервера немає. SDK один, а що може зробити виклик, визначає актор, який за ним стоїть: гравець, сервіс, мозок бота, оператор.

Головний сценарій, під який його спроєктовано, — машина гравця, що створює кімнату (room), а потім сама її веде. Це майстер-клієнт, який має інтерфейси власника кімнати (room owner) і нічого більше. У збірці з роллю room-visitor немає ні кіку, ні закриття кімнати: ці інтерфейси не вимкнено — їх там просто немає.

Права складаються з атомарних дозволів (permission atom), тож вбудованих рівнів ролей немає, а роль обмежує доступ до даних аж до рядка й стовпця. Див. Хто ухвалює рішення, а як записують видані права (grant) — на сторінці Access & Roles.

Один дизайн, один стек

Як це написано

SDK — це один дизайн і два способи його звузити, причому на нижчий рівень щось переходить лише тоді, коли вищий не може цього виразити. Спільні принципи однакові в кожному біндингу. Особливості мови охоплюють лише те, чого її парадигма не може виразити спільним способом. Особливості рушія — лише те, що рушій переробляє поверх своєї мови: в Unreal оголошення живе всередині макроса рефлексії самого рушія.

Як це працює

Код вашої гри звертається до модулів і більше ні до чого. Модулі зібрано з чотирьох примітивів — подій, RPC, даних і підписок, груп. Під ними лежить хаб, який ви ніколи не викликаєте: впровадження залежностей, монтування модулів, сесія, відновлення стану, якість обслуговування повідомлень. Ще нижче — транспортні адаптери (transport adapter), по одному на протокол. Який із них передасть виклик, ваш код не вирішує й навіть не помічає.

Обидві половини докладно — на сторінці Як побудовано SDK і далі аж до Під капотом.

Модулі компонуються, а не успадковуються

Базового модуля, від якого треба успадковуватися, немає, як немає й ієрархії, яку треба розширювати. Модулі утворюють граф, бо справжні фічі перетинають гілки: модуль Matchmaking резервує місця (seat) у кімнатах, випадання розміщує предмети через мапу, чат живе всередині кімнати.

Слово «успадкування» тут охоплює чотири різні механізми, і їх варто розрізняти. RPC сутності (entity) — частина самої сутності. Пресет — іменований набір аспектів, а не базовий клас. Щоб перевизначити крок платформи, досить поставити атрибут на свою заміну. Модуль запозичує інший модуль через декоратор, який звужує запозичений інтерфейс. Див. Успадкування і композиція.

Хто що бачить — вирішує оголошення, а не фільтр на клієнті

На сорок гравців (player) снапшот усієї кімнати ще годиться, на двісті — вже ні. Хто яку частину отримує, вирішують правила зони інтересу (interest rules). Персональні пакети для кожного актора й загальне розсилання — це два режими доставки однієї оголошеної моделі, тож перейти з одного на інший можна налаштуванням, без переписування коду. Далекі об’єкти, перш ніж зникнути, спрощуються за оголошеними рівнями деталізації (detail tier).

Це ще й питання безпеки: стан, який не повинен витекти, платформа просто не надсилає. Туман війни й поля, видимі лише власникові, відсутні в пакеті, а не приховані на клієнті. Глядачі, адміністратори й повтори бачать більше, бо мають ширші видані права. Див. Visibility.

Що лишається після втрати хоста

Якщо хост упав, матч на цьому не закінчується. Поки триває гра, платформа не копіює стан кімнати між хостами: власник один, тож порядок дій не потребує консенсусу. Матч виживає, бо його стан оголошено, а оголошений стан живе поза хостом: платформа робить його снапшот з оголошеним інтервалом. Новий хост продовжує з останнього снапшота.

Новий хост отримує весь стан на момент цього снапшота, тож усе, що відбулося після нього, втрачено. Деплой використовує той самий механізм, але без втрат: виведення хоста з роботи (drain) — це той самий шлях, що й перемикання на резерв, тільки пройдений навмисно.

Стан, що живе лише в рушії, не відновлюється

Стан, який ви тримаєте лише в акторах рушія, не оголошено, тож у нового хоста його не буде. ::: Докладніше — на сторінці Що лишається після втрати хоста, а про пільговий період (grace window), протягом якого гравець може повернутися в гру, — на сторінці Rooms.

Будь-який крок платформи можна замінити своїм

Кожен сценарій платформи — це ланцюжок зареєстрованих функцій, і будь-яку ланку можна замінити або обгорнути. Вхід, перевірка на вході в кімнату, покупка, надсилання результату, завантаження файлу — кожен такий крок має ім’я. Свою заміну ви оголошуєте атрибутом: версію можна обирати за умовою, а власний крок платформи лишається запасним варіантом.

Замість того щоб форкати код платформи, ви замінюєте її кроки. Див. Extensibility.

Один інтерфейс, шість мов

Один контракт, шість проєкцій: C#, TypeScript, Python і Go на сервері, згенеровані Unreal C++ і Unity C# у рушії. Кожен приклад коду на сайті показано всіма шістьма мовами. Якщо в біндингу немає інтерфейсу для якогось кроку, вкладка пояснює чому: крок виконується поза рушієм або право на такий виклик має інший актор.

Два наслідки варто знати, перш ніж обирати мову. RPC приймає об’єкти SDK за посиланням, а не сплощені DTO. А асинхронні примітиви вбудовані: канали, потоки даних (stream) і адресація груп. Тож можна звернутися до всієї групи й зібрати відповіді або обробляти файл частинами, поки він ще завантажується.

Є також детермінований хост у пам’яті: він запускає код вашої гри без жодного бекенда, а часом керуєте ви, тож тести детерміновані. Див. Потоки, час життя і тести.


Те, чого в SDK навмисно немає, — деплої, білінг, адміністрування організацій і користувачів — живе на операторському рівні. Бічна панель — це мапа всього іншого, а Перші кроки — найкоротший шлях усередину.