Протокол гри RTS


18

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

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

EDIT

Це повторне запитання від stackoverflow . Я виявив, що цей сайт був, мабуть, кращим місцем для питання.

Один з кращих відповідей з цього поста:

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


2
Відповідь дійсно залежить, який метод ви хочете використовувати. Клієнт - клієнт або клієнт - сервер. Клієнт для сервера простіше , але це вимагає довірчих серверів
Cem Kalyoncu

Відповіді:


25

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

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

Мінус полягає в тому, що кожен гравець так само повільний, як і найповільніший гравець - якщо хтось відстає в надсиланні команд, всі повинні сповільнитись і чекати, коли він наздожене (у Starcraft 2, це "XXX уповільнює гру " діалогове вікно " .


Насправді, є ще одне, що зазвичай робиться: усунути сервер взагалі . Нехай кожен клієнт надсилає свої команди кожному іншому клієнту. Це зменшує відставання (замість того, щоб команда переходила від вас -> сервер -> противник, вона просто йшла від вас -> противник) і полегшує кодування, оскільки вам більше не потрібно кодувати окремий сервер. Такий тип архітектури називається одноранговим (P2P).

Мінус полягає в тому, що зараз вам потрібен спосіб вирішення конфліктів, але оскільки команди гравців незалежні одна від одної у більшості RTS, це зазвичай не є великою проблемою. Крім того, він не масштабується - кожен раз, коли ви додаєте нового гравця, кожен гравець повинен надсилати йому свої команди. Ви не збираєтеся робити MMO RTS за допомогою P2P.


Ця настройка (надсилання лише команд за допомогою P2P) працює як більшість RTS, включаючи Starcraft, C&C, і AoE, і це єдиний спосіб, коли AoE може підтримувати 1500 одиниць на 28,8 кбіт / с .

(зображення мереж в AoE)

Ось ще кілька порад щодо написання P2P RTS:

  • З очевидних причин це налаштування може працювати лише в тому випадку, якщо ваша гра використовує фіксований час - ви не хочете, щоб результати обчислення залежали від частоти кадрів! Більшість речей з фіксованим кроком простіше працювати, тому це не повинно бути проблемою.
  • Щоб це працювало, результати кожної команди повинні бути повністю детермінованими .
    • Зазвичай це досить просто, якщо ви обмежитеся однією системою (наприклад, 32-бітної Windows) і змусите всіх клієнтів використовувати один і той же виконуваний файл: переконайтеся, що будь-які генератори випадкових чисел мають однакове насіння і завжди викликаються в одному порядку; бути надзвичайно обережним під час ітерації над не упорядкованими колекціями ; тощо.
    • Це вкрай складно, якщо ви плануєте зробити гру відтворюваною на різних платформах або (як це часто буває в Linux), дозволяючи клієнтам самостійно складати код. Мало того, різні системні бібліотеки , в значній мірі гарантується використання різних реалізацій rand(), і cos()т.д., але в значній мірі всі з плаваючою точкою математики може бути і мови (див тут , тут і тут ) ! У такому випадку вам може бути краще використовувати клієнт-сервер.
  • Ви хочете раз у раз надсилати всі позиції одиниць, хоча б під час налагодження, виявляти помилки десинхронізації (які, повірте, у вас будуть ). Чи будете ви тримати, що у фінальній грі залежить від вас - я б синхронізував принаймні деякі одиниці (або використовував якусь контрольну суму), щоб виявити спроби злому.

Гарний пост. Немало що додати, навіть ті ж компілятори оптимізують, налагодження / випуск та інші прапори можуть змінити результат. Будь обережний!
Пітер Ølsted

14

Я зробив RTS з мережею TCP, в якій я передав самі команди, а не результати команд . Наприклад, гравець дає наказ про переміщення. Якщо замовлення на переміщення дійсне відповідно до цього клієнта, воно надсилається на сервер. Потім сервер відправляє його назад усім клієнтам, які перевіряють його та виконують.

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

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

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

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

Щодо того, як можуть виглядати повідомлення Я не переймався ультра ефективністю, оскільки це була моя перша мережева гра. Я передав команди як рядки. Команди будуть відформатовані так:"<player_id>:<command>:<parameters>"

Для надуманого прикладу, команда переміщення може виглядати наступним чином : "3:move:522:100:200". Це означає , що Гравець 3хоче moveодиницю 522до ( 100, 200).

Сервер передає команду на всіх клієнтів, в тому числі той , хто послав його з номером кліща додається так: "153238:3:move:522:100:200".

Тоді всі клієнти виконували б цю команду, коли виконується галочка 153238.


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

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