🇬🇧 English | 🇺🇦 Українська
10. Сценарії розгортання¶
Той самий плагін поводиться по-різному залежно від того, де виконується код: в однокористувацькій грі, у мережевій сесії чи на виділеному сервері. Розділ про те, хто саме звертається до сховища в кожному випадку і що з цього випливає.
Коротка відповідь¶
| Хто звертається до сховища | Звідки ключі | Головна пастка | |
|---|---|---|---|
| Однокористувацька гра | Сам клієнт | Сценарій B або D | Вшитий ключ у збірці |
| Мережева гра (listen) | Хост, і лише він | Сценарій B | Кожен клієнт звертається сам і платить трафіком |
| Виділений сервер | Сервер | Змінні оточення | Спроба зробити те саме на клієнті |
| Настільний застосунок | Клієнт | Сценарій D | Ключі розробника замість ключів користувача |
Докладніше про самі сценарії — 3. Облікові дані.
Підсистема і мережа¶
US3Subsystem — це UGameInstanceSubsystem. Практичні наслідки:
- Вона існує в кожному екземплярі гри окремо: у клієнта своя, у сервера своя.
- У Play In Editor із кількома вікнами кожне вікно має власну підсистему й власного клієнта.
- Вона нічого не реплікує. Плагін не є мережевою системою: він робить HTTP-запити з того процесу, у якому його викликали.
Тому питання «а як воно працює в мультиплеєрі» насправді зводиться до питання «у якому процесі я викликаю ноду». Плагін не вирішує це за вас — і не має вирішувати.
Однокористувацька гра¶
Найпростіший випадок: є один процес, він і звертається до сховища.
Типові задачі — хмарні збереження, завантаження користувацького вмісту, вивантаження знімків чи звітів про збої.
Що робити:
- Ключі — за сценарієм B2 (короткоживучі від вашого бекенда) або B1 (підписані посилання). Якщо бекенда немає взагалі, а бакет належить користувачеві — сценарій D.
- Виклик із будь-якого місця: Blueprint актора, віджета, Game Instance.
- Пам'ятайте, що операція асинхронна: гра продовжує йти, поки вона виконується.
Приклад: хмарне збереження
Event Save Game
│
├─► Save Game to Slot (звичайне локальне збереження)
│
└─► Get S3 Subsystem → Get Default S3 Client → S3 Upload File
Bucket : Get Default Bucket
Object Key : saves/{PlayerId}/slot1.sav
File Path : (шлях до збереженого файлу)
│
├─ On Success → показати «збережено у хмару»
└─ On Failure → лишити локальне збереження й спробувати пізніше
Порядок тут не випадковий: спершу зберігаємо локально, потім вивантажуємо. Якщо мережі немає, гравець не втрачає прогрес — він просто не синхронізований.
Мережева гра: listen-сервер¶
Хост — це водночас і сервер, і гравець. Решта підключаються до нього.
Головне рішення: хто звертається до сховища.
Варіант 1 — тільки хост (рекомендований)¶
Хост зберігає стан світу, вивантажує його, роздає результати іншим через звичайну реплікацію.
Event Save World State (виконується на сервері)
│
├─ Switch Has Authority
│ ├─ Authority → S3 Upload File → (успіх) → Multicast: «світ збережено»
│ └─ Remote → нічого не робити
Чому так: одне звернення замість N, один набір ключів замість N, і немає потреби давати
право запису кожному клієнтові.
Варіант 2 — кожен клієнт сам¶
Виправдано, коли дані належать конкретному гравцеві й нікого більше не стосуються: його власні скріншоти, його налаштування, його профіль.
Тоді кожен клієнт має отримати свої короткоживучі ключі з політикою, що обмежує його
власним префіксом (users/${user_id}/*). Спільний ключ на всіх — це можливість перезаписати
чужі дані.
Чого не варто робити¶
Не викликайте ноду і на сервері, і на клієнтах, не подумавши. Blueprint-подія, яка виконується скрізь, у сесії на вісьмох дасть вісім однакових завантажень одного файлу — за вісім оплачених запитів, із непередбачуваним порядком запису.
Перевіряйте Has Authority (або Switch Has Authority) там, де операція має бути одна.
Виділений сервер¶
Найзручніший випадок із погляду безпеки: бінарник сервера у гравців не буває, тож довгоживучі ключі тут доречні.
Що робити:
- Credential Source →
Environment variables. - Ключі задає середовище запуску: змінні процесу, роль інстанса, менеджер секретів.
- Клієнти не звертаються до сховища взагалі — або звертаються лише за підписаними посиланнями, які видає сервер.
# systemd unit, Docker, скрипт запуску - будь-що, що ставить оточення
export AWS_ACCESS_KEY_ID=...
export AWS_SECRET_ACCESS_KEY=...
./MyGameServer -log
Особливості серверної збірки¶
Плагін працює без світу й без актора. Затримки між повторами відлічує FTSTicker, а не
таймер світу, тож операції коректно виконуються під час завантаження карти, у консольній
утиліті й у commandlet.
Модуль тестів у серверну збірку не потрапляє — він має тип DeveloperTool і збирається
лише для редактора та Development.
Секцій Editor Only на сервері немає. Це не обмеження, а гарантія: те, що ви вписали в редакторі, не могло поїхати в збірку. На сервері працюють лише змінні оточення або те, що ви встановили кодом.
Роздача підписаних посилань¶
Типова схема, коли клієнт має щось завантажити, але ключів мати не повинен:
Клієнт: RPC до сервера — «хочу залити збереження»
│
Сервер: перевіряє право, далі
│ Make Presigned URL (PUT, 900 секунд)
│
└─► повертає адресу клієнтові
│
Клієнт: звичайний HTTP PUT за цією адресою
Клієнт при цьому може бути налаштований як Anonymous — підписувати йому нічого.
Настільний застосунок¶
Бакет належить користувачеві. Сценарій D: екран введення ключів, зашифроване локальне
сховище, Local user store.
Дві поради, які економлять час:
- Дайте профілю осмислене ім'я (
Local Store Profile Name), а неdefault, якщо застосунків у вас кілька: так ключі одного не побачить інший. - Перевіряйте ключі одразу після введення — зробіть кнопку «Перевірити», яка викликає
S3 List Objectsз лімітом 1. Помилка одразу після введення зрозуміла; та сама помилка через півгодини під час першого справжнього збереження — ні.
Play In Editor: що варто знати¶
- Кожне вікно PIE — окремий екземпляр гри, тож і клієнт у кожного свій.
- Ключі беруться з редакторських секцій (див. 3. Облікові дані) — зібрана гра поводитиметься інакше, і це навмисно.
- Запустивши PIE у режимі виділеного сервера, ви отримаєте той самий поділ, що й у бою:
перевіряти
Has Authorityварто саме тут, а не після пакування.
Клієнти в PIE окремі, а диск — спільний. Вікна PIE є окремими екземплярами гри, але живуть в одному процесі й пишуть в один і той самий
Saved/. Для передавань це має практичний наслідок: два екземпляри, які виконують той самий граф із тим самимLocal File Path, працюють з одним файлом на диску. Найпомітніше це наS3 Download File Chunked— обидва відкриють один<файл>.s3partі писатимуть у нього навперемін, зіпсувавши результат; записи про відновлення вSaved/S3/теж спільні, бо їх ідентифікатор рахується з бакета, ключа й шляху, а вони в обох однакові.Це не специфіка PIE як такої — так само поводяться дві копії зібраної гри, запущені з однієї теки на одній машині. Рішення те саме, що й у «Чого не варто робити»: або
Has Authorityтам, де передавання має бути одне, або різнийLocal File Pathдля кожного екземпляра.
Контрольний список перед релізом¶
- [ ] У
DefaultGame.iniі в ассетах профілів немає ключів. - [ ] Credential Source відповідає способу постачання (не
Environment variablesу грі, яку завантажують гравці). - [ ] Операції, які мають виконуватися один раз, захищені перевіркою
Has Authority. - [ ] Політика ключа звужена до потрібних дій і потрібного префікса.
- [ ] Помилки мережі оброблені: у гравця має бути зрозуміла поведінка без інтернету.
- [ ] Великі передавання можна скасувати, і скасування перевірено — див. 5. Передавання файлів.
- [ ] Ключі, якими ви користувалися під час розробки, перевипущені перед публікацією.
- [ ]
S3.Live.*прогнано проти вашого власного бакета й провайдера, а не лише проти налаштувань за замовчуванням — див. 9. Тестування.
Далі: 11. Поширені запитання · див. також 13. Профілі на практиці, де ті самі конфігурації показано через ассети профілів і джерела облікових даних