[Перевод] Мультиплеер в быстрых играх(Часть IV: Хэдшот! Путешествуем во времени)

76febf4741f34ba1b08aa31f02f44662.jpg

  1. Части I, II (синглплеер с авторитарным сервером)
  2. Часть III (Появление врага)
  3. Часть IV (Хэдшот!)


Как повесить идеальный хэдшот если у тебя пинг 2 секунды? Вы узнаете в этой статье.

Текущий алгоритм работы мультиплеера


  • Сервер получает команды с клиентов и времена их отправления
  • Сервер обновляет состояние мира
  • Сервер с некоторой частотой отправляет свое состояние всем клиентам
  • Клиент отправляет команды и локально воспроизводит их результат
  • Клиент получает обновленные состояния мира и:
    • Применяет состояние от сервера
    • Заново применяет все свои команды, которые сервер не успел применить.
    • Интерполирует предыдущие состояния других игроков
  • С точки зрения игрока, есть два серьезных последствия:
    • Игрок видит себя в настоящем
    • Игрок видит других в прошлом.


Обычно это отлично работает, но это становится большой проблемой для событий, которым нужна высокая пространственно-временная точность. Например если хочется разнести врагу бошку!

Компенсация лага


Вот вы прицелились своей снайперской винтовкой прямиком в голову сопернику. Вы на выдохе спокойно спустили курок. Вы уверены в своих силах, вы не можете промахнуться.

Но вы промахнулись!

Почему это произошло? Как такое случилось?

Дело в том, что в архитектуре, которую мы построили, вы целитесь в место, где голова врага была за 100 мс до выстрела, не в то время когда вы выстрелили!
e2ce97335d604cc29683fb6c0d6e9afa.gif
Это как быть снайпером в мире, где скорость света безумно, просто ничтожно мала. Вы целитесь в соперника, но к тому моменту, как до вас дошел свет, его уже давно нет на старой позиции.

Слава богу, есть довольно простое решение для этой проблемы, которое так же приемлемо и для других игроков большую часть времени (с одним исключением, о котором речь пойдет позже).

Вот как это работает:

  • Когда вы стреляете, клиент отправляет событие выстрела сервера, содержащее серверное время состояния, которое отображалось в момент выстрела. И точное направление вашего оружия.
  • Это КЛЮЧЕВОЙ момент. Так как сервер все равно рассылает свое состояние каждый кадр по клиентам, он может восстановить любой момент из прошлого. В том числе, он может восстановить мир в точности таким, каким его видел клиент в момент выстрела.
  • Таким образом сервер оставляет стрелка в том положении, в котором он находится; а весь остальной мир меняет на то состояние, которое клиент отображал в момент выстрела, т.е. возвращает назад во времени.
  • Сервер обрабатывает выстрел и получает его результат.
  • Сервер возвращает весь мир в текущее состояние времени.
  • Сервер применяет результат выстрела и рассылает обновления по клиентам как обычно.


И все счастливы!
fea4f79f50814a4b9bf9caaf89e82555.gif
Сервер счастлив потому что он сервер. Он всегда счастлив, ведь он всегда прав.
Стрелок счастлив, потому что он целился в голову врага и разнес её одним точным выстрелом.
Убитый — единственный, кто может быть недоволен. Если он стоял на месте в момент выстрела, он сам и виноват. Если он бежал, значит вы хороший стрелок.
Но что если он перебежал через опасную зону, а доли секунды спустя его застрелили, когда он думал что находится в безопасности? Он будет огорчен.
0128796031ad4d4dac686c07742e705a.gif

Вот это может произойти. Это — компромисс, на который мы вынуждены пойти. Так как стрелок застрелил его в прошлом, игрок может быть застрелен после того как он уже спрятался за угол.

Это звучит нечестно, но будем помнить о том, что с точки зрения стрелка этот игрок перебегал через площадь столько же времени, сколько и с точки зрения игрока. Единственная разница — это задержка.

Было бы гораздо хуже, если бы точный выстрел не сработал!

Доводим до абсурда


Важно заметить, что этот метод работает даже при гигантском пинге.
Внимание, трюк выполнен профессионалами! Не выполняйте этот трюк на рабочем сервере! Команды с давностью в две секунды не надо выполнять в реальной жизни.

de5c135437a84e30a0cc951d7c8427a2.gif

Заключение


Такую вещь как мультиплеер сложно сделать правильно, но если вы вооружены пониманием описанных концепций, ничего безумного сложного в реализации нет.

Материалы для дальнейшего прочтения (англ. яз.):
Gaffer On Games
Valve’s latency compensation methods

От переводчика
На этом заканчивается серия статей от Gabriel Gambetta.
Но я с вами не прощаюсь. Я еще собраюсь написать статью о том, как построить сериализацию игрового мира, да и вообще никогда не знаешь куда тебя заведет исследование такой интересной темы как мультиплеер!

© Habrahabr.ru