Мультиплеер швидких іграх (Частина III: поява ворога)



  1. Частини I, II (синглплеер з авторитарним сервером)
  2. Частина III (Поява ворога)
  3. Частина IV (Хедшот!)
Введення
У першій статті я розповів про авторитарний сервер і його корисність для захисту від читів. У результаті другої частини ми отримали набір технік, що дозволяють гравцеві контролювати персонажа на віддаленому сервері без лага.

У цій статті ми розглянемо наслідки одночасного підключення кількох гравців до одного сервера.

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

Частота оновлення сервера
У попередній статті поведінку сервера було гранично простим — він зчитує введення клієнта; оновлює стан гри; відправляє його назад на клієнт. Але коли клієнтів багато, вони дуже часто відправляють команди. Оновлення ігрового світу для кожної команди і подальше оповіщення всіх клієнтів про зміненому стані грунтовно нагрузило б процесор і мережу.

Більш вдалим підходом було б накопичувати всі команди без виконання. Натомість світ буде оновлюватися періодично з низькою частотою, наприклад 10 разів в секунду. Під час кожного оновлення всі накопичені команди застосовуються(можливо з кількома кроками фізики, щоб вона була більш стабільною) і новий стан гри розсилається клієнтам.
Прим. Перекл. У швидких іграх ви швидше за все захочете виставити частоту оновлення не менше 20 разів в секунду(як у Overwatch) і піднімати його аж до 120 (як в CS:GO).

Коротко кажучи, у ігрового світу є власна фіксована частота оновлення, не залежить від наявності команд або їх кількості.

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

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

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





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

Екстраполяція
Припустимо, що ви робите гонки. Машини досить передбачувані — якщо машина їде 100 м/с, через секунду вона буде приблизно на 100 метрів попереду від того місця, де вона була.

Чому «приблизно»? У перебігу цієї секунди машина могла трохи прискоритися, або загальмувати; трохи повернутися. Ключове слово тут — трохи. Машини влаштовані так, що позиція переважно залежить від попередньої позиції, швидкості і напрямку; і меншою мірою від дій користувача. Іншими словами, гоночна машина не може миттєво розвернутися на 180 градусів.

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

Ця корекція може бути великою або маленькою залежно від безлічі параметрів. Якщо гравець вів машину прямо і не змінював швидкість, экстраполированная позиція ідеально співпаде зі скоригованої. З іншого боку, якщо гравець врізався у щось, передбачена позиція буде абсолютно неправильна.

Цей метод підійде тільки для об'єктів з великою інерцією: машини, кораблі.

Інтерполяція
Є ситуації коли екстраполяція взагалі не може бути застосована. Власне, у всіх сценаріях, де напрямок та швидкість персонажа змінюються швидко. Наприклад в 3d шутере гравці зазвичай, зупиняються і огинають перешкоди на великих швидкостях, роблячи екстраполяцію безглуздою, так як позиції не можуть бути передбачені з застарілої інформації.

При цьому ви все ще не можете наївно застосовувати оновлення з сервера: гравці будуть переміщуватися кожні 100 мс і при кожному втрачений/затриманому пакеті.

У вас є інформація про позиції ворогів кожні 100 мс. Так що трюк полягає в тому, щоб показувати гравцеві що відбувалося між цими оновленнями в минулому.

Нехай ви отримуєте позиції в момент t = 1000. Ви вже отримали інформацію проt = 900, так що відt = 1000t = 1100, ви показуєте що цей гравець робив з t = 900t = 1000. Таким чином ви показуєте даний пересування ворогів, але на 100 мс пізніше.



Врахуйте, що при використанні цієї техніки гравці бачать трохи різний стан світу, так як себе гравець бачить в теперішньому часі(це необхідно для відсутність лага при введенні), а ворогів бачить у минулому(це було б навіть без інтерполяції, з-за ненульового пінгу). Але навіть у швидких іграх затримка на 100 мс зазвичай непомітна.



Але є винятки — якщо потрібна висока просторова і тимчасова точність, наприклад, при пострілі одного гравця на іншого. Так як інші гравці видно в минулому, ви цілитеся з затримкою в 100 мс + пінг, тобто туди, де ворог був більше 100 мс тому! З цим ми будемо розбиратися в наступній статті.


Підсумок
У клієнт-серверної моделі з авторитарним сервером, рідкісними оновленнями і затримками у зв'язку, ви все одно повинні дати гравцеві ілюзію безперервного руху. У попередній частині ми розглядали способи миттєво реагувати на користувальницький введення використовуючи передбачення на стороні клієнта та узгодження з сервером.

Але інші гравці все ще для нас було проблемою. У цій статті ми розглянули два способи впоратися з ними:

Екстраполяція — застосовується коли позиція може бути передбачена виходячи з попередньої інформації — позиції, швидкості і прискорення.

Інтерполяція — не пророкує майбутнє, а використовує тільки реальну інформацію, надану сервером, показуючи ворожих гравців з недавнього минулого.

В результаті гравець бачить себе в сьогоденні, а решту гравців — в минулому. Зазвичай це створює відмінний ігровий досвід.

Але якщо більше нічого не робити, ілюзія зламається коли події вимагатимуть високою просторово-часової точності, наприклад при пострілі.
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.