Як синхронізувати годинник через мережу для розробки ігор?


10

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

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

Гра програмується на Java та Python (паралельна розробка як проект)


7
шукати ntp
ratchet freak

5
Я впевнений, що це питання висвітлено вже на сайті gamedev.stackexchange.com, або принаймні воно там належить.
congusbongus

1
@CongXu: Я не такий впевнений. Хоча це завдання, як правило, виконується для ігор, воно не притаманне певному розвитку ігор. Багато інших розподілених систем потребують синхронізованих годин.
Ян Худек

2
Ви вже намагалися використовувати опцію IPIM4 TIMESTAMP? Більше інформації можна знайти за адресою linux.die.net/man/7/socket до linux.die.net/man/3/cmsg, а потім невеличка прикладна програма на pdbuchan.com/rawsock/rawsock.html остання перед початком Розділ IPv6.
ott--

2
Ігри (програми) не повинні торкатися системного годинника.
Відновити Моніку - М. Шредер

Відповіді:


9

Я думаю , що це, безумовно , НЕ ОК , щоб synchornize годинник в системі . Користувач не очікує, що ти торкнешся системних налаштувань, і багато систем навіть не дозволять тобі це зробити.

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

Основна ідея може полягати в тому, що з кожним надісланим вами пакетом тимчасової мітки ви надіслали її та порядковий номер та часова мітка, коли ви отримали останній пакет з іншого боку. Виходячи з цього, ви обчислюєте зворотну пряму: Наприклад, якщо пакет Q каже, що він був відправлений у 1000, а пакет P був отриманий у 500, ніж якщо ви надіслали пакет P при 0, а Q отримуєте у 800, то обернене значення (800 - 0 ) - (1000 - 500) = 300. Неможливо знати асиметрію, тому ви просто припускаєте, що пакет бере половину (150) тиків у будь-якому напрямку. І ця віддалена мітка часу випереджає місцеву на 1000 - (800 - 150) = 350 кліщів. Зворотній шлях буде різним. Якщо ви вважаєте, що годинник досить точний, вам слід використовувати довгострокове середнє співвідношення.

Зверніть увагу, що ви також не хочете використовувати системний годинник для годинника. Вони можуть отримати ресинхронізацію посередині, відкинувши вас з колії. Ви повинні використовувати clock(CLOCK_MONOTONIC)в Unix або GetTickCountв Windows (не впевнені, як ці API зараз у Java або Python).


Примітка: Параметр SO_TIMESTAMPsocket (див. Socket (7), згаданий ott-- у коментарі до питання) був би корисний для відокремлення ефекту затримки циклу подій, який отримує пакети. Чи варто того докладати зусиль, залежить від того, наскільки хороша точність вам потрібна.


1

Як ви знаєте, який годинник гравця правильний? Ви цього не зробите, тому використовуйте опорний годинник .

Тут перенасичений NTP - вам потрібна лише ~ 1 секунда точності, тому використовуйте rdate або виберіть щось із багатьох алгоритмів синхронізації годин.

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


1

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

  • Скільки часу минуло з попереднього кадру, щоб ви могли пересувати будь-які речі, засновані на часі. Це може бути різним для клієнта та сервера, якщо обидва галочки з різною швидкістю (наприклад, іноді ви можете бачити сервери, які працюють на фіксованій 20 ГГц (або що завгодно), але клієнтів, яким дозволено запускати так швидко, як вони хочуть).
  • Скільки часу минуло з моменту запуску поточної карти. Це нульовий таймер (просто запускайте його до 0 для клієнта та сервера при їх запуску), і час сервера вважається "головним", тому сервер надсилає клієнту поточний вигляд цього часу для кожного кадру що працює на сервері. Це можна отримати, взявши поточний час сервера і віднісши час, коли сервер запустився, або шляхом накопичення часу за кадром вище. Наведений вище час кадру на рівні клієнта також може використовуватися для генерації точок інтерполяції між будь-якими двома послідовними кадрами сервера.
  • Довідковий "базовий час", з якого просувається весь інший час; це може бути (але не обов’язково бути для всіх типів гри) однаковим як для клієнта, так і для сервера і ініціалізуватися на початку гри (або поточної карти), але ніколи не змінюватися після (за винятком нової гри - або нової карти) - запускається).

Це спрощений контур - я не намагаюся вирішувати такі питання, як затримка / випали пакети / тощо - але це основна основа, на якій має базуватися вся справа.

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

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