Синхронізація клієнтів з низьким трафіком із сервером у MMO


22

Я реалізую MMO, коли гравець летить у космос на своєму зірковому кораблі, керуючи ним клавішами зі стрілками та співпрацюючи з іншими гравцями.

Я хочу реалізувати це так, що гравець зможе ухилитися від свого корабля від ракети або чогось іншого, тому я намагаюся передбачити цілий стан гри на стороні клієнта, використовуючи той самий алгоритм імітації світового режиму, що і сервер. Цей ігровий світ написаний на C # і буде викликаний безпосередньо в клієнті (він написаний на Unity3D) і через CLR на сервері C ++ (під Linux). Підключення через UDP.

Проблема полягає в тому, як підтримувати, наприклад, 1000 гравців на одній карті (виключаючи всі інші ігрові об’єкти, мофи ...): Скажімо, я буду:

  • синхронізувати сервер із клієнтами 50 разів на секунду
  • надсилати кожному клієнту стану саме тих ігрових об’єктів (та гравців), які він може бачити (в деякому радіусі)
  • повинні відправити 100 об’єктів кожному гравцеві в радіусі його перегляду
  • повинен надсилати в середньому 50 байт на ігровий об’єкт (це id, x, y координати, обертання, стан ...)

значить, знадобиться така пропускна здатність мережі: 1000 (клієнти) * 50 (раз в секунду) * 100 (об'єкти, що надсилаються кожному гравцю) * 50 (байти на об'єкт) = 250 000 000 байт в секунду! Це неможливо!

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

У будь-якому випадку, як такі ігри запрограмовані у загальному вигляді? Дякую.


1
Я надсилаю просто логічну інформацію про об'єкти (положення в світі, поточний стан (який є одним байтом) тощо) - ніякої графіки.
Слав

1
@ Слав: Приємно! Весь цей біт зміщення нагадує мені про мої дні програмування ASM.
Рандольф Річардсон

1
Чому б не "сьогоднішні дні"? :) Коли я пишу на AS3, Java, Lua, C # і стикаюся з такою низькою продуктивністю, мені не вистачає C ++ і згадую про ASM.
Слав

1
@ Слав: Хе-хе, я останнім часом не робив багато ASM. Більшість речей для мене є сьогодні в Java та Perl (здебільшого mod_perl2), але я дуже полюбляю і ці мови.
Рендольф Річардсон

2
@Slav, ви писали: "Коли я пишу на AS3, Java, Lua, C # і стикаюся з такою низькою продуктивністю, я сумую за C ++ і пам'ятаю про ASM". Ви повинні навчитися правильно користуватися Lua та C #, можливо, ви вважаєте, що продуктивність є менш неправомірною. Крім того, скарги на (нібито) найшвидший мову сценаріїв там є в кращому випадку єдиним ... Це гра про аналіз геному людини в реальному часі?
Дощ

Відповіді:


20

Вам потрібно лише близько 30 оновлень (а то й менше, можливо, 10 чи 20) за секунду. інтерполювати позиції клієнта, що рухається, на сторону. Загалом, ви повинні надсилати дані лише тоді, коли це дійсно потрібно. У WoW ви можете отримувати більше оновлень від гравців, з якими ви перебуваєте в групі, ніж від гравців, які перебувають в одному місці. Крім того, якщо інший гравець далеко від вас, ви не отримуєте стільки оновлень за секунду про нього.

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

Потім скористайтеся BitVectors або howevery, ви можете зателефонувати їм, щоб зменшити кількість непотрібних даних! Приклад: Ви також можете спробувати записати поплавок, використовуючи лише один байт (в діапазоні від 0 до 1 або -1 до 1), щоб у вас було лише 256 або 128 різних значень. Але гравець не помітить жодних ривкових рухів завдяки інтерполяціям.

Подивіться на приклад із LidgrenLibrary про те, як стискати дані: http://code.google.com/p/lidgren-network-gen3/wiki/Optimization

Далі: Спробуйте зменшити радіус перегляду гравців під час їх переміщення і лише передавати важливу інформацію за цей час. Потім, коли вони зупиняються, знову збільшуйте радіус зору. Ви можете використовувати систему просторового хешування або дерево bsp, щоб зменшити накладні витрати на пошук об'єктів, які знаходяться "в діапазоні". Це хороше прочитання теми: http://en.wikipedia.org/wiki/Collision_detection

Також стискайте дані, ЩО ВАМ САМО ВИ знаєте про структуру даних та часову узгодженість даних (що можна і потрібно використовувати). Загальний алгоритм, такий як Bzip2, Deflate, як би там не було, слід використовувати, але лише як завершальний етап стиснення!

Крім того, для інформації, яка не є важливою для гри, ви також можете використовувати додаткові методи P2P. Приклад: Гравець грає в анімацію "привіт" (Просто графічний ефект) Гравець передає цю інформацію на сервер, але сервер не передає інформацію іншим гравцям. Натомість цей некритичний ефект відтворюється самим гравцем іншим клієнтам у діапазоні.

EDIT (через коментар):

Додаткові методи зменшити середню кількість бітів в секунду для кожного гравця:

  1. Ви написали, що відправляєте "Об'єкт не змінився". Причин для цього немає. Якщо ви турбуєтеся про втрату пакету (і через те, що ваше моделювання не синхронізується через це), врахуйте наступне: На кожному фіксованому часовому кроці (наприклад, 100, 200, 300, 400 ...) хеш-стан стану моделювання та надішліть його на сервер . сервер підтверджує або надсилає повний знімок всіх даних назад.

  2. Для таких речей, як ракети або навіть гравці, ви можете використовувати не тільки інтерполяцію, але й екстраполяцію, щоб зробити моделювання більш реалістичним. Приклад "Ракета": Замість оновлення повідомленнями типу "Зараз у позиції х" просто надішліть повідомлення, що містить таке: "Ракета породила: позиція (вектор), Час (на етапі моделювання ракети породжувались), швидкість ( вектор) ". Таким чином, вам навіть не потрібно включати обертання, тому що наконечник завжди буде в напрямку "швидкості".

  3. Поєднайте кілька команд в одному повідомленні і ніколи не надсилайте повідомлення розміром менше 16-20 байт, оскільки заголовок udp буде більшим, ніж саме повідомлення. Також не надсилайте пакети, більші за MTU вашого протоколу, оскільки фрагментація сповільнить швидкість передачі.


О, це гарна ідея оновлювати деякі об'єкти частіше, ніж інші, використовувати P2P, погіршувати точність з плаваючою комою, надсилати лише зміни (що для мене не тривіально, оскільки я мав намір періодично синхронізувати об'єкти, але "об'єкт не змінювався" - це інформація теж). З усіма цими модифікаціями вся картина виглядає реалістичніше!
Слав

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

5

Ось два підходи:

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

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

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

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

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

І +1 за те, що робити математику, занадто багато людей не спромоглися зробити прості оцінки ресурсів.


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

3
Це означає цілі числа та фіксований крок часу. Теоретично ви можете знущатися з плаваючими точками, щоб поводитися, але використовувати цілі числа - це простіше. Ви зрозуміли приклад зниклого ракети, якщо ви використовуєте недетерміновану фізику, можливо, найкраще дозволити серверу повною мірою боротися зі смертю та швидко передавати випадки загибелі / руйнування.
aaaaaaaaaaaa

5

Спочатку кілька питань.

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

Взагалі, хоча майже немає причин для того, щоб: A) мати тактову частоту 50 Гц ((Більшість стрільців отримують 15-20 і MMO менше, ніж це.) B) надсилають повний стан кожному кадру. (Чи взагалі має значення обертання ракети в космосі? Чи можна просто припустити, що "фронт" орієнтований уздовж вектора, який він подорожує?)

Приділіть час передбаченню та інтерполяції, і ви побачите, що ваша пропускна здатність зменшиться. Проект, над яким я працював, мав швидкість оновлення 10 ГГц, і представлення стану об'єкта, я думаю, становить 14 байт. (Стисніть усе, що можете! Я вважаю, що ми використовували 6 біт для визначення обертання навколо площини x, а потім ще 6 біт для нахилу над / під цією площиною.

Ще одна річ, яку ви можете зробити - це розставити пріоритети об'єктам. Покажіть, можливо, у відповідному наборі є 100 об’єктів, але чи знаєте ви його перегляд фрустуму на сервері? Якщо чогось немає на його думку, чи можете ви упустити частоту оновлення на порядок?

Загальна ідея не полягає в тому, щоб зробити ідеального моделювання на клієнті, це неможливо, ідея - зробити веселу гру, де гравці не помітять, що це не ідеальне моделювання.

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