Інтерполяція позицій у багатокористувацькій грі


14

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

Коли я отримую повідомлення про оновлення об'єкта, я обчислюю час, коли очікую наступного оновлення:

origin = serverCurrentPosition
diff = serverNextPosition - origin
arriveTime = now + timeBetweenTicks * updateRate

Коли я малюю об'єкт, я обчислюю час, що залишився до наступного оновлення, і відповідно інтерполюю позицію:

step = 100 / timeBetweenTicks * updateRate
delta = 1 - step * ((arriveTime - now) / 100)
position = origin + diff * delta

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

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


Привіт Іво. Я думаю, що це хороша тема, але незрозуміло, що робить ваш код - наприклад, звідки беруться serverCurrentPosition, serverNextPosition, timeBetweenTicks?
CiscoIPPhone

Це надсилання даних оновлення, які надходять із сервера.
Іво Ветцель

Відповіді:


11

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

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

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

Ще одна ідея зменшити тремтіння у ваших налаштуваннях: оскільки ви передаєте як поточну, так і «наступну» координати, ви можете обчислити швидкість об’єкта. Потім, коли оновлення затримується, ви не зупиняєте об'єкт у його пункті призначення (тобто "наступному" положенні), але продовжуєте рухати його з однаковою швидкістю. Якщо ваші об'єкти не змінюють швидкості, це дійсно покращить плавність руху клієнта.


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

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

9

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

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

Я включив багато деталей про цей підхід в моєму попередньому відповіді тут


Гм, я щось подібне робив у попередній версії, неточність з плаваючою комою часом зробила це дуже погано, у мене досить великі часові плани між оновленнями, до 300 мс для деяких об'єктів, але, можливо, я просто зробив це неправильно, я дам це знімок, коли я знаходжу трохи вільного часу :)
Іво Ветцель

Точність з плаваючою точкою насправді взагалі не повинна входити до цього! Ви читали мою пов'язану відповідь про stackoverflow? Він охоплює всі деталі реалізації такого роду речей.
Мартін

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