Мультиплеєрний платформер - чи зазвичай потрібні корективи сервера для одного клієнта на сервері?


10

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

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

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

Клієнтський цикл (один раз на кадр, раз на 16,67 мс)

Спрощений цикл клієнта виглядає так:

  1. Перевірте місцевий вхід (WASD) і запакуйте їх як дії (наприклад Type=MoveLeft, Time=132.0902, ID=15). Ми зберігаємо упаковані дії, щоб з часом їх надсилати пізніше. Також ми безпосередньо застосовуємо бажану дію до локального фізичного моделювання гри. Наприклад, якщо ми маємо MoveLeftдію, ми застосовуємо силу вліво на швидкість гравця.

  2. Поставте прапорець, щоб надіслати дії. Щоб запобігти зловживанню пропускною здатністю клієнта, надсилайте лише упаковані дії через певні інтервали (наприклад, 30 мс).

  3. Застосувати модифікації сервера. У певний момент це буде обробляти дельти та виправлення, отримані сервером, і застосовувати їх до локального моделювання гри. Для цього конкретного питання це не використовується.

  4. Оновіть місцеву фізику. Запустіть цикл фізики на головному плеєрі. В основному, це прогнозує рух гравця на стороні клієнта. Це додає гравітації швидкості гравця, застосовує швидкість гравця до його позиції, фіксує зіткнення по дорозі і т. Д. Я повинен зазначити, що фізичне моделювання завжди виконується з фіксованою дельта-секундою (називається багаторазовою залежністю від реальних дельта секунд) .

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

Цикл сервера (кожні 15 мс)

Спрощений цикл сервера виглядає так:

  1. Обробляйте дії. Перевірте отримані пакети дій від клієнтів та застосуйте їх до моделювання фізики сервера. Наприклад, ми могли б отримати 5 MoveLeftдій, і ми застосували б силу до швидкості 5 разів . Важливо зауважити, цілий пакет дій виконується на одному "кадрі" , навпаки клієнту, де він застосовується, як тільки дія відбувається.

  2. Оновіть логіку гри. Ми оновлюємо фізику гри, переміщення гравців та виправлення зіткнень і т. Д. Ми також пакуємо будь-які важливі події, які траплялися надіслані гравцям (наприклад, здоров'я гравця впало, гравець помер тощо).

  3. Надішліть виправлення. Ми регулярно (наприклад, раз на 35 хвилин) надсилаємо дельти іншим гравцям (наприклад, позиції гравців, стан здоров'я тощо), якщо вони нещодавно змінилися. Ця частина наразі не реалізована, тому що я хочу, щоб моделювання одного гравця дало однакові результати на клієнті та сервері без виправлень, щоб переконатися, що прогноз на стороні клієнта працює добре.

Проблема

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

Синхронізація чудово працює при простому зіткненні / русі

Будь ласка, ігноруйте графіку прототипу. Білий прямокутник = гравець, червоний прямокутник = перешкоди, синій - фон

Однак, я отримую помилки синхронізації, роблячи рухи, залежні від часу, такі як стрибки та переміщення близько до ізольованої перешкоди:

Синхронізація не працює, тому що я стрибнув навколо зазначеної перешкоди в моменти, залежні від часу

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

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

Питання

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

Я продумав певні можливі рішення, з якими мені менш комфортно:

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

  2. Використовуйте наданий клієнтом час, щоб застосувати бажані дії. Я думаю, це було б схоже на компенсацію відставання, вимагаючи "повернутися у часі" та перевірити на рух. Начебто ви хочете застосувати корективи сервера, поверніться у часі і повторіть наступні дії після цього. Мені дуже не подобається ідея. Це виглядає складно, дорого в ресурсах і вимагає довіритися заданому часу клієнта (хоча я дійсно планую перевірити, чи час виглядає відносно законним).

  3. Попросіть GameDevelopment StackExchange для нової чудової ідеї, яка виправить усі мої проблеми.

Я тільки починаю в світі ігрових мереж, тому, будь ласка, не соромтесь виправляти / критикувати / ображати будь-яку з вищезгаданих концепцій або давати ідеї / ресурси, які могли б допомогти мені на шляху мого подорожі до Чудового світу мереж. Вибачте, якщо я міг би знайти свою відповідь деінде, я не зазнав цього.

Дуже дякую за дорогоцінний час.


Ваш сервер і клієнт запускають кадри з різною швидкістю. Що станеться, якщо клієнт виконує дві дії на послідовних кадрах, але сервер бачить один кадр між ними?
користувач253751

@immibis базувався на gafferongames.com/game-physics/fix-your-timestep, щоб мінімізувати цей ефект.
Джессі Емонд

Відповіді:


11

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

Клієнт повинен поширитись від простого надсилання повідомлень "Я стрибнув" до відправки повідомлень "Я перейшов з X, Y в момент T". Потім сервер перевіряє, що місце розташування знаходиться в безпосередній близькості від того, що, на його думку, гравця було в момент T (що ви можете обмежити порівняно невеликим часом в минулому) для захисту від обману, а потім імітує стрибок з позиції клієнта надісланий. Сервер виправляє клієнта лише тоді, коли він далеко від удару (як правило, через відставання чи подібне).

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


Дуже цікаво. Я спробую це втілити і побачити, як це відбувається. Дуже дякую, що знайшли час для відповіді. До речі, ви згадали "в безпосередній близькості" і "досить мало часу в минулому", ви просто перевіряли б з постійною відстані і часу відповідно? Або ви використовуєте більш складні методи, такі як збереження історії позицій та використання середнього часу клієнта (або що-небудь ще, насправді)?
Джессі Емонд

Що б не працювало для вашої гри. Почніть просто, ускладнюйте це лише до тієї міри, яку вважаєте за потрібну. Деякі сервери зберігають історію подібних знімків для ~max(RTT)кліщів сервера в минулому, але чи потрібно вам для вашої гри конкретно, я не знаю. Це може бути ще зручніше для ігор у стилі стрілялки, де ви також хочете виконати певний рівень виявлення ударів / пострілів у клієнта, і вам потрібно не лише знати, де грав 46 км тому, але і де його ціль була 46 мс тому і де будь-яка переміщення оклюзійних платформ, куди.
Шон Міддлічч

Ідеально. Я експериментую і побачу, що найкраще працює. Позначивши це як прийняту відповідь, ще раз дякую!
Джессі Емонд
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.