Как сделать рассинхрон в онлайн играх
Рассинхрон
Gospodin_Blinoff #1 Отправлено 06 сен 2013 – 14:38
Хотелось бы получить ответ от кого-нибудь от разработчиков, что значит понятие “рассинхрон” в игре и как он происходит?
Например, я так понимаю, связь с сервером осуществляется при помощи пакетов, которые передают клиент и сервер друг другу. Клиент передаёт серверу пакеты о действиях игрока, сервер клиенту – о действиях других игроков и обработанные данные о взаимодействии с игровым миром, полёте снарядов, пробитии брони и нанесённом уроне. Клиент игры всё это интерполирует и мы получаем непрерывную картинку. Для меня не совсем понятно, как может получаться так, что данные о движении танка обрабатываются правильно, а о полёте снарядов нет, например, при пролетании снарядов сквозь танк.
Разработчики, расскажите, пожалуйста, поподробнее, как происходит обмен данными между сервером и клиентом, как формируются пакеты, получаемые от клиента и сервера? Думаю многим будет это интересно, даже если будет много сложных терминов, желание разобраться есть. Мне кажется, это даже можно отнести к игровой механике, и это может помочь, например, при “уворачивании” от снарядов а-ля Джов.
RenamedUser_18117268 #2 Отправлено 06 сен 2013 – 14:42
Gospodin_Blinoff (06 Сен 2013 – 14:38) писал:
Хотелось бы получить ответ от кого-нибудь от разработчиков, что значит понятие “рассинхрон” в игре и как он происходит?
Например, я так понимаю, связь с сервером осуществляется при помощи пакетов, которые передают клиент и сервер друг другу. Клиент передаёт серверу пакеты о действиях игрока, сервер клиенту – о действиях других игроков и обработанные данные о взаимодействии с игровым миром, полёте снарядов, пробитии брони и нанесённом уроне. Клиент игры всё это интерполирует и мы получаем непрерывную картинку. Для меня не совсем понятно, как может получаться так, что данные о движении танка обрабатываются правильно, а о полёте снарядов нет, например, при пролетании снарядов сквозь танк.
Разработчики, расскажите, пожалуйста, поподробнее, как происходит обмен данными между сервером и клиентом, как формируются пакеты, получаемые от клиента и сервера? Думаю многим будет это интересно, даже если будет много сложных терминов, желание разобраться есть. Мне кажется, это даже можно отнести к игровой механике, и это может помочь, например, при “уворачивании” от снарядов а-ля Джов.
enepomnyaschih
Супер-пупер школа программирования
Исследование идеального UI Framework’а, программирование игр, веб-программирование, задачи и решения
При реализации любой игры, допускающей соединение клиентов через LAN или интернет возникает проблема синхронизации. У разных клиентов разная скорость передачи пакета к серверу и обратно, но не хотелось бы, чтобы клиент с хорошей скоростью доступа страдал из-за медленных клиентов.
Реальное и игровое время
Будем различать понятия реального времени и игрового времени. Реальное время – это время в формате h:m:s.ms, в котором мы живем и которое сейчас у нас на часах. Игровое время – это количество прошедших итераций игры. То есть у каждой игры в реальном времени есть свой внутренний таймер, который отмеряет игровые итерации. Ускорение и замедление игры вызывает увеличение и уменьшение частоты таймера игрового времени соответственно.
Пусть таймер игрового времени при нормальной скорости игры имеет частоту 100 итераций в секунду.
Реальное время 15:00:00.000. Игровое время – 0. Начинается игра.
Реальное время 15:00:10.000. Игровое время – 1000. Игрок нажимает на паузу.
Реальное время 15:00:30.000. Игровое время не изменилось – 1000. Игрок продолжает игру.
Реальное время 15:00:40.000. Игровое время – 2000. Игрок ускоряет игру в 2 раза.
Реальное время 15:00:50.000. Игровое время идет быстрее – 4000.
Варианты синхронизации
Пусть имеется игра с частотой таймера игрового времени 100 раз в секунду. Пусть имеется сервер С и 2 клиента А и Б со скоростями доступа 20 мс и 200 мс соответственно (2 итерации и 20 итераций игрового времени). Протокол соединения поддерживает возможность передачи пакетов как от клиента к серверу, так и обратно.
Простейшая схема, которая приходит в голову: в один и тот же момент реального времени игровое время на разных хостах совпадает. То есть хосты идут синхронно, параллельно друг другу.
Если клиент А отдает команду, что персонаж хочет идти вперед, то на сервер посылается запрос. Проходит (t) итераций игрового времени. В момент получения запроса (t0) сервер может пойти тремя путями:
- Представить, что команда выполнилась на итерации (t0 – t) и попытаться восстановить историю событий до момента (t0). После чего разослать эту информацию всем клиентам, которые, в свою очередь попытаются восстановить историю событий от момента (t0) до момента прихода пакета (синхронный вариант с предсказанием).
- Выполнить команду на итерации (t0) и разослать эту информацию всем клиентам. Клиенты, получив эту информацию пытаются восстановить историю событий от момента (t0) до момента прихода пакета (простойсинхронный вариант).
- Взять наибольшее время доставки пакета – 20 итераций и поставить команду на выполнение через 20 итераций. При этом отправить всем клиентам информацию о выполнении команды (синхронный вариант с перестраховкой).
Рассмотрим эти схемы более подробно.
Синхронный вариант с предсказанием
Игровое время – 0. Клиент А отдает команду. Посылается запрос на сервер. Клиент А сразу начинает двигать персонаж, не дожидаясь ответа от сервера.
Игровое время – 2. Сервер принимает пакет. Сервер представляет, что в момент 0 выполнилась данная команда и воспроизводит историю до текущего момента. Сервер отправляет пакет на клиент Б.
Игровое время – 22. Клиент Б принимает пакет. Он пытается воспроизвести историю событий до текущего момента и показывает ее на экране.
Преимущества
- Клиент А выполняет действие сразу, безо всякой задержки
Недостатки
- История воспроизводится дважды, что может привести к рассинхронизации и багам
- На клиенте Б в момент приема пакета проявляется жестокий лаг, как персонаж А прыгает
- Система поддается взлому. Достаточно клиенту А послать запрос с указанием очень давнего момента времени, как вся история игры пересчитывается, как вам угодно. И сервер ничего не может с этим поделать. Он всего лишь воспроизводит команды по просьбе клиента. А в реальности игровым процессом управляет клиент
Несмотря на свои недостатки, эта схема часто встречается в практике начинающих программистов. Все игры, известные мне и написанные по приведенному протоколу синхронизации, имели тучи багов и полностью отказывались работать через минуту игры на плохом Интернете (пинг
Простой синхронный вариант
Игровое время – 0. Клиент А отдает команду. Посылается запрос на сервер. Клиент А ждет ответа от сервера.
Игровое время – 2. Сервер принимает пакет. Сервер выполняет команду в момент 2 и рассылает клиентам сигнал о событии.
Игровое время – 4. Клиент А принимает пакет. Он пытается воспроизвести историю событий до текущего момента и показывает ее на экране.
Игровое время – 22. Клиент Б принимает пакет. Он пытается воспроизвести историю событий до текущего момента и показывает ее на экране.
Преимущества
- Система устойчива к взлому. Все действия изначально порождаются на сервере и запросы от клиента к серверу не содержат информации об игровом времени
- Лаги уменьшаются в 2 раза по размеру
Недостатки
- История все еще воспроизводится на клиентах, что может привести к рассинхронизации и багам
- Лаги проявляются на всех клиентах, даже на клиенте А, несмотря на то, что он спровоцировал событие
Синхронный вариант с перестраховкой
Игровое время – 0. Клиент А отдает команду. Посылается запрос на сервер. Клиент А ждет ответа от сервера.
Игровое время – 2. Сервер принимает пакет. Сервер, зная наибольшее время доставки пакета – 20 итераций, рассылает клиентам информацию о том, что в момент 22 происходит событие.
Игровое время – 4. Клиент А принимает пакет. Он запоминает, что в момент 22 персонаж двинется вперед.
Игровое время – 22. Клиент Б принимает пакет. Везде синхронно обрабатывается событие, как на сервере, так и на клиентах.
Преимущества
- Система устойчива к взлому. Все действия изначально порождаются на сервере и запросы от клиента к серверу не содержат информации об игровом времени
- Лагов нет, история не воспроизводится
Недостатки
- Приходится постоянно держать свежую информацию о пинге всех клиентов
- Наличие всего лишь одного клиента с большой задержкой дает задержку на всех клиентах – даже клиент А с хорошей сетью вынужден ждать 220 мс до совершения действия
- Система слабо устойчива к вариациям пинга. Что, если пакет идет до клиента Б не 20 итераций, а 25? Прийдется как-то исхитряться, воспроизводя историю этих 5 итераций
Казалось бы, ничего лучше придумать нельзя. Тем не менее, есть один вариант, кардинально отличающийся от предложенных –
Асинхронная синхронизация
Ядром такого типа синхронизации является тезис о том, что игровое время в один и тот же момент реального времени на разных хостах разное. При этом сервер всегда впереди, а клиенты отстают от него на время доставки к ним пакета от сервера.
Как такое возможно? Очень просто! Достаточно периодически отмерять пинг каждого клиента и отодвигать клиенты в игровом времени на то самое время передачи пакета от сервера к клиенту. Представьте, что перед вами рядом стоят клиенты А и Б. И вы ясно видите, что все действия на клиенте А совершаются на 180 мс раньше, чем на клиенте Б. Это сыграет ключевую роль в протоколе. Сразу обратимся к примеру и все станет ясно.
Игровое время: С/А/Б – 100/98/80. Клиент А отдает приказ о движении вперед. Отправляется запрос на сервер и ожидается ответ.
Игровое время: С/А/Б – 102/100/82. Сервер принял пакет. Сервер выполняет команду и начинает двигать персонаж вперед в 102 момент времени. Сервер рассылает информацию об этом клиентам.
Игровое время: С/А/Б – 104/102/84. Как раз в 102 момент игрового времени клиент А принял пакет о том, что в 102 момент времени персонаж начинает идти вперед . Клиент сразу реагирует на событие и воспроизводит команду.
Игровое время: С/А/Б – 122/120/102. Как раз в 102 момент игрового времени клиент Б принял пакет о том, что в 102 момент времени персонаж начинает идти вперед. Клиент сразу реагирует на событие и воспроизводит команду.
Задержка на клиенте А от момента нажатия на кнопку до выполнения действия составила 4 итерации, то есть как раз пинг – то самое время, которое пакет идет от клиента к серверу и обратно.
Игровое время: С/А/Б – 100/98/80. Клиент Б отдает приказ о движении вперед. Отправляется запрос на сервер и ожидается ответ.
Игровое время: С/А/Б – 120/118/100. Сервер принял пакет. Сервер выполняет команду и начинает двигать персонаж вперед в 120 момент времени. Сервер рассылает информацию об этом клиентам.
Игровое время: С/А/Б – 122/120/102. Как раз в 120 момент игрового времени клиент А принял пакет о том, что в 120 момент времени персонаж начинает идти вперед. Клиент сразу реагирует на событие и воспроизводит команду.
Игровое время: С/А/Б – 140/138/120. Как раз в 120 момент игрового времени клиент Б принял пакет о том, что в 120 момент времени персонаж начинает идти вперед. Клиент сразу реагирует на событие и воспроизводит команду.
Задержка на клиенте Б от момента нажатия на кнопку до выполнения действия составила 40 итераций, то есть как раз пинг – то самое время, которое пакет идет от клиентак серверу и обратно.
Преимущества
- Никаких лагов
- Никаких воспроизведений истории
- Никаких лишних задержек, только необходимые
- Задержка зависит только от вашей собственной сети, и никак не зависит от других клиентов
- Система устойчива к взлому. Все действия изначально порождаются на сервере и запросы от клиента к серверу не содержат информации об игровом времени
- Система гибкая – мы можем свободно варьировать отставанием клентов от сервера при вариациях пинга. Правда, при этом игра будет похожа на слайд-шоу, но зато без багов
- Система проста в реализации
Недостатки
- Приходится постоянно держать свежую информацию о пинге всех клиентов
- Имеется вынужденная задержка, зависящая от скорости вашей сети
Мне кажется, приведенные недостатки с запасом перебиваются преимуществами данной схемы. Данная схема по внешним симптомам, очевидно, используется во многих популярных играх, таких как Warcraft 3 и World of Warcraft.
В реализации своих игр я буду использовать асинхронную синхронизацию, пока не найду что-нибудь получше. Если вы сделаете это быстрее меня, жду ссылок и комментариев =)
Рассинхрон
Gospodin_Blinoff #1 Отправлено 06 сен 2013 – 14:38
Хотелось бы получить ответ от кого-нибудь от разработчиков, что значит понятие “рассинхрон” в игре и как он происходит?
Например, я так понимаю, связь с сервером осуществляется при помощи пакетов, которые передают клиент и сервер друг другу. Клиент передаёт серверу пакеты о действиях игрока, сервер клиенту – о действиях других игроков и обработанные данные о взаимодействии с игровым миром, полёте снарядов, пробитии брони и нанесённом уроне. Клиент игры всё это интерполирует и мы получаем непрерывную картинку. Для меня не совсем понятно, как может получаться так, что данные о движении танка обрабатываются правильно, а о полёте снарядов нет, например, при пролетании снарядов сквозь танк.
Разработчики, расскажите, пожалуйста, поподробнее, как происходит обмен данными между сервером и клиентом, как формируются пакеты, получаемые от клиента и сервера? Думаю многим будет это интересно, даже если будет много сложных терминов, желание разобраться есть. Мне кажется, это даже можно отнести к игровой механике, и это может помочь, например, при “уворачивании” от снарядов а-ля Джов.
RenamedUser_18117268 #2 Отправлено 06 сен 2013 – 14:42
Gospodin_Blinoff (06 Сен 2013 – 14:38) писал:
Хотелось бы получить ответ от кого-нибудь от разработчиков, что значит понятие “рассинхрон” в игре и как он происходит?
Например, я так понимаю, связь с сервером осуществляется при помощи пакетов, которые передают клиент и сервер друг другу. Клиент передаёт серверу пакеты о действиях игрока, сервер клиенту – о действиях других игроков и обработанные данные о взаимодействии с игровым миром, полёте снарядов, пробитии брони и нанесённом уроне. Клиент игры всё это интерполирует и мы получаем непрерывную картинку. Для меня не совсем понятно, как может получаться так, что данные о движении танка обрабатываются правильно, а о полёте снарядов нет, например, при пролетании снарядов сквозь танк.
Разработчики, расскажите, пожалуйста, поподробнее, как происходит обмен данными между сервером и клиентом, как формируются пакеты, получаемые от клиента и сервера? Думаю многим будет это интересно, даже если будет много сложных терминов, желание разобраться есть. Мне кажется, это даже можно отнести к игровой механике, и это может помочь, например, при “уворачивании” от снарядов а-ля Джов.
Источники:
https://forum.worldoftanks.ru/index.php?/topic/990631-%D1%80%D0%B0%D1%81%D1%81%D0%B8%D0%BD%D1%85%D1%80%D0%BE%D0%BD/
https://enepomnyaschih.livejournal.com/1610.html
https://forum.worldoftanks.ru/index.php?/topic/990631-%D1%80%D0%B0%D1%81%D1%81%D0%B8%D0%BD%D1%85%D1%80%D0%BE%D0%BD/