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

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

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


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

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

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


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

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

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

Дело в том, что в архитектуре, которую мы построили, вы целитесь в место, где голова врага была за 100 мс до выстрела, не в то время когда вы выстрелили!



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

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

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

И все счастливы!



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



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

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

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

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


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




Заключение


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

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

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


UPD


krimtsev задал весьма резонный вопрос.
FPS и PING понятно как влияют на это, а что скажете на счет TICKRATE?

Отвечаю. Мы с bogotoff позволили себе отойти от описанного алгоритма, так как нам показалось неудобным играть при частоте обновления сервера 10 раз в секунду.

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



Хотя игра при такой частоте сервера, конечно, выглядит ужасно. Не делайте так. И вообще держите FPS как можно выше. Чем больше частота дискретизации игрового мира, тем более качественный игровой опыт будет у игрока. Хотя мое личное ИМХО что выше 60 — уже не имеет смысла.
Поделиться с друзьями
-->

Комментарии (71)


  1. krimtsev
    09.06.2016 16:27
    +3

    ну FPS и PING понятно как влияют на это, а что скажете на счет TICKRATE?


    1. marsermd
      09.06.2016 16:34

      В нашей реализации мы позволили себе отойти от описанного в статье и внедрили интерполяцию на сервере при выстреле. Так что даже при TickRate = 1 и простой траектории врага попадание было идеальным (хоть конечно и выглядело это отвратительно).
      Я пожалуй опишу эту технику в этой статье.


  1. amarao
    09.06.2016 16:59
    +1

    Как обрабатывается ситуация, когда другой игрок (2), уже «забежавший за угол» стреляет в игрока (1) и, вроде бы, тоже в голову? У него на экране «прошлое» (т.е. он видит игрока (1), который ещё не выстрелил), он попадает в игрока(1). Игрок (1) видит на экране «прошлое» (игрок(2) бежит за угол) стреляет, попадает.


    1. marsermd
      09.06.2016 17:05
      +1

      Во-первых, обычно анимация смерти начинается только после получения стейта с сервера, где говорится, что игрок умер (обратите внимание, в нашей демке сделано именно так.)
      А далее разные игры обрабатывают такие ситуации по разному:

      • Оба игрока умирают(т.к. оба игрока совершили выстрел пока еще были живы и оба попали в своего врага).
      • Игрок, команда которого дошла до сервера первой, остается вживых. Т.е. когда команда на выстрел доходит до сервера, сначала сервер проверяет, жив ли игрок в данный момент времени, и только если жив проводит рейкаст в прошлом.


    1. unclejocker
      09.06.2016 17:13
      +3

      в том же overwatch часто бывают ситуации «выстрелили друг в друга и оба умерли»…


      1. krimtsev
        09.06.2016 17:25

        а вот в CS:GO именно так как описал автор. Иногда и поражает, почему ты вроде стрельнул первый, а даже не попал


      1. neomedved
        09.06.2016 18:05

        Если не ошибаюсь, в Overwatch просто есть Ханзо с медленными стрелами.


        1. unclejocker
          09.06.2016 20:06

          это понятно, но я имел в ивду солдата и вот это все, с пулями.


      1. EvilNW
        09.06.2016 18:05

        Смею предположить, что все дело в скорости полета пули.
        В CS:GO выстрел настигает жертву мгновенно
        В Overwatch почти у всех персонажей есть скорость полета «пули», кроме Трейсер, DV-a Солдата-76 и похоже Вдовы. Выстрелам остальных героев требуется время, чтобы добраться до конечной точки координат.


      1. Sabin
        09.06.2016 22:03

        В Overwatch и уже за углом от выстрела вдовы помирал много раз


    1. syrompe
      09.06.2016 17:28

      У «пули» как правило в шутерах тоже есть ограничение скорости.
      Вы живы, вы выстрелили, пуля полетела, соперник жив.
      Соперник жив, соперник выстрелил, пуля полетела, вы тоже живы.

      Тут «пули» долетают до целей и оба погибают.


      1. marsermd
        09.06.2016 18:10

        Обычно пули наоборот не существуют в физическом мире)
        Вместо полета пули выполняется один рейкаст, как бы предполагая что скорость пули бесконечна.


        1. eightrichazikon
          09.06.2016 21:13

          А в батле реализовано в виде пуль из колизии или пускают рэйкаст и считают время и баллистику?:) (Особенно в танках)


          1. marsermd
            09.06.2016 21:16

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


            1. eightrichazikon
              10.06.2016 08:51

              А не подскажете хороший материал по мультиплееру в гонках? особенно о столкновениях?)


              1. marsermd
                10.06.2016 11:26

                Я бы заглянул на Gaffer On Games чтобы про физику прочитать.
                Но пока никаких годных материалов специализирующихся на гонках не видел.


      1. wsf
        10.06.2016 16:44

        Тут все зависит от реализации «пули» в конкретном движке, в том же кс пуля — это инстахит (как его еще называют хитскан), то есть, по факту — вектор, и сервер просто проверяет прохождение вектора через интересующую точку. Могу даже более конкретный пример привести — unreal tournament 2003/2004 — там вся игровая логика написана на джавоподобном unrealscript который легко разбирается в исходники, где конкретно видна такая реализация. В батлфилде же, пуля — это прожектаил который имеет свою скорость и на него действует глобальная физика, кстати, в батлфилде стрельба рассчитывается частично на клиенте, дабы снизить нагрузку с сервера по моделированию всех физических взаимодействий.


  1. Alex_ME
    09.06.2016 17:21
    +1

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


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


    А вот интересно, при довольно сложном мире, где много объектов, которые могут на что-то влиять, как это осуществляют? Меняют ли состояние всех объектов? Или как-то выбирают те, которые могут влиять?


    1. marsermd
      09.06.2016 17:30

      Сервер должен должен интерполировать состояние между кадрами, между которыми интерполирует игрок. Это не вполне одно и то же, так как буфер кадров для интерполяции может быть больше чем на два кадра:)

      А вот интересно, при довольно сложном мире, где много объектов, которые могут на что-то влиять, как это осуществляют? Меняют ли состояние всех объектов? Или как-то выбирают те, которые могут влиять?

      Очевидно, ответ зависит от конкретной ситуации. Если у вас шутер с комнатами по 15 человек и меняются только свойства игроков, можно смело откатывать весь мир.
      Если у вас MMO с интерактивным миром, стоит откатить только небольшое окружение игрока.


      1. afrokick
        11.06.2016 13:28

        А еще можно хранить дельту мира между стейтами, и тогда объем должен быть в разы меньше, если изменений не очень много. И тем более есть смысл отсылать дельту игрокам.

        Откатывать тоже просто — просто применять по очереди все изменения мира.

        Для тех, кто первый раз слышит о дельте — это разность двух состояний.

        К примеру, есть состояние А, в котором у игрока П1 100хп, у игрока П2 — 80хп. И вот игрок П2 наносит урон игроку П1 в размере 30единиц.

        Теперь состояние мира Б выглядит так:
        П1 — 70хп
        П2 — 80хп

        Дельта двух состояний:
        П1 -30хп

        Можно отправить состояние Б с данными:
        П1 — 70хп
        П2 — 80хп

        Или отправить дельту А и Б:
        П1 -30хп

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

        Для огромных миров, например как майнкрафт, это экономит огромное количество трафика (там еще всякие чанки и компрессии)


        1. marsermd
          11.06.2016 14:03

          Верно. Единственная проблема дельта-компрессии в том, что для отображения n-ного состояния мира, нужно получить все состояния от 0 до n, а значит надо посылать состояния через reliable протокол, построенный над udp)


          1. afrokick
            11.06.2016 15:25

            не совсем понял зачем. Для нового игрока на серваке всегда лежит последний n-ый снимок мира как раз для этого случая. А больше вроде бы случаев и нет, разве что откат на несколько состояний назад для просчета физики/etc. Всем остальным игрокам можно слать дельты


            1. marsermd
              11.06.2016 17:35

              Я говорю о том, что до клиента так или иначе должны доходить ВСЕ дельты. Это обязательно, иначе будет расхождение в мире.
              Пусть изначальное состояние
              X = 0.

              Delta 0
              X += 1
              Delta 1
              X -= 1
              Delta 2
              X += 1

              Если, например, Delta1 не дойдет до клиента, у него X будет всегда на единицу больше чем надо.
              Значит надо чтобы все дельты дошли. Так как UDP не гарантирует доставки пакетов, а использовать TCP — самоубийство, надо строить reliable протокол над UDP.


  1. gsaw
    09.06.2016 17:22
    +1

    Что значит «Интерполирует предыдущие состояния других игроков»? Клиент получает положение и вектора других игроков и расчитывает новое положение?

    Может быть такая ситуация. Стрелок целится в голову жертвы по версии стрелка. По версии жертвы она успела уйти в сторону. Как будет разруливаться такая ситуация? Тот кто раньше сообщил свое состояние (малый пинг) тот и полбедил?


    1. marsermd
      09.06.2016 17:42

      Что значит «Интерполирует предыдущие состояния других игроков»? Клиент получает положение и вектора других игроков и расчитывает новое положение?

      Интерполяция — это значит, что клиент, условно говоря, передвигает врага между двумя устаревшими кадрами.
      Прочитайте предыдущую часть для более подробного объяснения.

      Может быть такая ситуация. Стрелок целится в голову жертвы по версии стрелка. По версии жертвы она успела уйти в сторону. Как будет разруливаться такая ситуация? Тот кто раньше сообщил свое состояние (малый пинг) тот и полбедил?

      Прочитайте и первую часть тоже. Сервер авторитарный. Что говорит сервер — то и правда.
      Сервер для определения попадания откатывает время назад, так что если стрелок с точки зрения его клиента попал, он скорее всего попадет.


      1. gsaw
        09.06.2016 18:32

        В той же Destiny упоминался некий «судья» (точный термин не помню, в голове перевел как «судья» или «модератор»), которого они постоянно там фиксят, что бы сбалансировать game experience игроков с разными пингами. Судя по статье тут такого нет, чисто математика и никакой эвристики или чего то подобного.


        1. Imposeren
          09.06.2016 23:37

          Можно предположить что если сервер/клиент занимаются интерполяциями, то большой пинг в «правильные» моменты вполне может быть преимуществом, т.к. «мозгом» становится тоже проще интерполировать. Можно даже чит написать который будет по хоткею какой-то неведомой магией пытаться поднять пинг на 100-200мс.

          Это все чисто предположения, но да: по хорошему нужен судья который будет не только откатывать/интерполировать, но и учитывать текущие пинги обоих игроков


          1. gsaw
            15.06.2016 12:46

            Ну да, так и есть. Было в Дестини, сейчас не знаю. У людей с высоким пингом было приемущество. В большинстве случаев они из стычек один-на-один выходили победителями. Были даже читеры, специально лагали, что бы выжить. Стоит такой лагающий, в него все лупят, а ему хоть бы хны. Внезаптно он оживает и все умерли.


  1. tmin10
    09.06.2016 17:22
    +1

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


    1. marsermd
      09.06.2016 17:43

      Скорее всего слишком много ваших пакетов потерялось.
      Интерполяция — это нахождение промежуточного положения между двумя крайними точками, так что она тут никак не поможет.
      А экстраполяция не применяется в шутерах для положений персонажей.
      Прочитайте предыдущую часть для более подробного объяснения.


  1. Luchnik22
    09.06.2016 17:46
    +1

    Отдельное спасибо за подборку


  1. aleshqq
    09.06.2016 18:05
    +1

    Можно ли получить доступ к демке для исследований? Не нашел ссылку в статьях и спрашиваю с надеждой, что вы просто забыли добавить ее :)


    1. marsermd
      09.06.2016 18:07

      Код демки находится в не самом лучшем состоянии. Так что его выкладывать не будем, а то научится кто-нибудь на свою голову. А вот вопрос о хостинге WebGL примера думаем.


  1. sergTsarikovskiy
    09.06.2016 18:08
    +1

    очень познавательно, спасибо


  1. Carry
    09.06.2016 19:16
    +2

    По опыту игры в Q3 через dial-up и пингом 200...400 предполагал именно такое положение дел.
    Интересно, какие еще есть приемы для повышения играбельности при высокой и нестабильной задержке.


    1. marsermd
      09.06.2016 21:12

      А вам не хватает указанных техник, при которых игра играбельна даже при пинге в 2 секунды и обновлениях сервера раз в секунду?:)
      Или вы имеете в виду альтернативы?


  1. Saffron
    09.06.2016 19:57

    Я такой алгоритм предвидел, ещё когда вы первую часть статьи перевели. И проблема, которую я тогда сформулировал актуальна и в этой реализации. Что если два игрока читят совместно, Петя имеет намеренно большой лаг, Вася — минимальный, между собой у них связь через быструю локальную сеть. Тогда Вася живёт в будущем относительно Пети. И может в прошлое Пети посылать информацию о том, что только будет происходить. А значит Петя будет обладать информацией о будущем, и сможет использовать её для читинга. Например, невидимка нападает на персонажа Васи. Вася передаёт информацию о невидимке в прошлое и Петя реагирует на неё, применяя защитное заклинание на персонажа Васи.

    И как будет вести себя сервер, если таких читеров не один и не два, а полсервера? Какие причудливые бои будут разворачиваться.


    1. marsermd
      09.06.2016 21:08

      Да, разумеется так можно обмануть систему. Правда профита на практике немного выйдет. Максимальный пинг, который бы я поддерживал у себя на сервере — секунда. И то кратковременно. Как показывает практика, с пингом 500 играть просто нереально.
      Вы успеете понять что надо делать по команде вашего друга за полсекунды? А ведь ваш друг еще должен тратить свой самый ценный ресурс — внимание на то чтобы следить за происходящим вокруг вас. На закуску. Скорость реакции среднего человека на внезапное событие 250 мс. Можете проверить вашу скорость реакции вот тут. Таким образом пока ваш друг отреагирует на событие + пока вы отреагируете на сообщение друга, пройдет в лучшем случае 500 мс. Знакомое число? И это мы считаем, что друг вас уколол иголкой, а не словами сказал.
      А еще с пингом 500 играть банально не удобно. Обычно если два игрока отправляют команды на убийства друг друга, в живых остается тот, чья команда дошла до сервера быстрее.


      1. Saffron
        10.06.2016 00:23

        Очевидно, что реагировать будет компьютер. Помните, в стандартный мапхак диаблы включалась функциональность мгновенного дисконнекта при опускание хитов ниже предела? Так и здесь, будет целый программный набор читера. Например, можно транслировать картинку от Васи Пете непрерывно. Вдобавок к перехвату пакетов, которые позволяют видеть всю in-game информацию, потому что редко кто озабочивается, чтобы невидимое для игрока делать невидимым на стороне сервера, а не клиента.

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

        Разве? Давайте посчитаем. Пусть Семён играет с реальным лагом в 1 секунду и виртуальным лагом в 5 секунд, а Иван с настоящим лагом в 1 секунду. Петя помогает семёну и тоже имеет лаг в 1 секунду. На 2 секунде Иван атакует Семёна, на третьей секунде команда семёна дошла до сервера и сервер «убил» Семёна. На четвёртой секунде об этом узнал Петя и немедленно уведомил об этом Семёна. Тот тут же послал сигнал «убить Ивана», который дошёл до сервера на 5 секунде. Сервер вычел эмулируемый лаг в 5 секунд и посчитал, что семён стрелял на нулевой секунде, а значит успел первым. Семён оживает, Иван умирает.


        1. marsermd
          10.06.2016 11:34

          Вот всей этой канители с оживаниями никто не делает. Если человек мертв в настоящий момент на сервере, пришедшая команда на выстрел уже не сработает.
          Если игрок убит, он не будет воскрешен даже если выяснится, что его убийцу «убили» раньше.

          А если рассматривать программные хаки, так гораздо удобнее для реализации предоставленных уязвимостей, скажем, отображать всех врагов вне зависимости от того, видны ли они. Все равно эта информация скорее всего доходит до клиента.
          Или классический AutoAim, который по зажатию кнопки будет целиться в голову врага.
          А это не имеет никакого отношения к механизму лагокомпенсации:)


          1. Saffron
            10.06.2016 13:09

            > Вот всей этой канители с оживаниями никто не делает.
            То есть реальность отличается от изложенной в статье теории? Но допустим, но ведь это нечестно. Для настоящих лагающих, а не фейкающих.


            1. marsermd
              10.06.2016 15:03

              Нет, не отличается. В статье описан механизм компенсации лагов следующим образом:

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

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

              Если хотите, можете применять выстрелы в прошлом, флаг вам в руки разбираться с применением ввода остальных игроков, потому что там нехилые временные парадоксы возникнуть могут. И иногда получаются настоящие петли времени, из которых не очень понятно как выходить.


          1. VitalatroN
            15.06.2016 09:17

            Тоже про AutoAim подумал в процессе чтения статьи. Я правильно понимаю что с такой техникой нарушается авторитарность сервера? Похоже что клиент теперь может сказать серверу: а вот когда враг пробегал через щель, я ему прям в нос выстрелил!


            1. marsermd
              15.06.2016 11:01

              Авторитарность сервера не так-то сильно и нарушается. Для AutoAim не нужна лагокомпенсация. Клиент знает положение врага?
              Знает.
              Значит может выстрелить ему в нос в реальном времени. Зачем для этого в прошлое возвращаться?


  1. TimsTims
    09.06.2016 20:36

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


    1. marsermd
      09.06.2016 21:10

      Я бы грешил на хитбоксы если честно. Ну и еще напомню что в КС есть такое понятие как

      разброс
      image


      1. TimsTims
        10.06.2016 09:07

        Поверьте моему опыту, это не разброс. Это замечаешь сразу, пересаживаешься с пинга 30 на пинг 90. Стиль игры и навыки не меняются за один день, и я абсолютно точно вижу, что стрелял чуть выше головы, сидя и с прицела sg553(b-4-4), а попадание засчитывается. При пинге 30 такого ни разу не случалось.
        Естественно, я не говорю про спрей, когда выпускается вся обойма


        1. marsermd
          10.06.2016 11:34

          Забавно. Может быть они действительно увеличивали хитбоксы для игроков с плохим пингом)


    1. youROCK
      09.06.2016 23:46

      Я помню, в КС версии так 1.3 был нечестный прием — можно было искусственно задерживать отправку пакетов до сервера, и при этом, поскольку все выстрелы просчитывались на сервере и сервер «верил» времени и положению, которое прислал клиент, в вас практически невозможно было попасть, поскольку вы на самом деле уже были в другом месте и сервер это учитывал. В Quake 3 вроде бы нужно как раз стрелять туда, где находится соперник у тебя на экране, а в CS было так, что стрелять надо с некоторым «упреждением», именно из-за другого алгоритма расчета попаданий на сервере.


      1. marsermd
        10.06.2016 11:35

        Я гарантирую что в Quake надо стрелять на опережение)


  1. Mercury13
    09.06.2016 23:22
    +1

    Почему мужик с пистолетом не лысый?


  1. 007913
    10.06.2016 11:35

    Подскажите, а есть такое явление что в некоторых играх скорость игрока с большим пингом(например 150мс) медленнее чем обычно для игрока с пингом 10мс, тоесть именно плавное замедление а не скачками?
    Как применимы ли ваши алгоритмы к компенсации скорости передвижения?


    1. marsermd
      10.06.2016 11:37

      Медленнее?? Это очень неожиданное явление. Сомневаюсь, что это возможно, речь обычно идет о задержке, а не замедлении. Возможно вам начинают посылать пакеты более редко, так что движение визуально получается более гладкое, из-за этого и появляется ощущение замедленности.


  1. Amenum
    10.06.2016 11:37

    Довольно интересная статья. Идет ли речь о «настоящем» откате времени для всего мира или это просто расчет точки попадания на мониторе первого игрока и отправка численного урона убежавшему второму игроку?

    Давайте представим ситуацию, когда выстрел не убивает. Первый игрок стреляет и попадает. У второго брызжет кровь, выпадает из рук оружие и он прихрамывая бежит дальше. Допустим, второй игрок в своем времени убежал на полсекунды от места столкновения. Кровь и снаряжение остались позади. Но он не убит (допустим был в шлеме), а его физические характеристики должны были измениться. Спрашивается, с какого момента? Раненный он не мог бежать с той же скоростью и за полсекунды пробегает уже меньше.

    Допустим, это не выстрел, а удар в рукопашной с последующей анимацией броска через спину с прогиба. Второго игрока надо телепортировать? «Эй, парень, ты тут уже полсекунды на земле лежишь, нажми кнопку встать!»

    Второй игрок имеет щит, которым может на 400мс прикрываться от летящих в него пуль с кулдауном 400мс. Пинг первого 500мс, второго — 0. Что делать?

    В общем, каковы ограничения физической модели игры и каковы ограничения отката времени?


    1. marsermd
      10.06.2016 11:42

      Обычно речь идет о применении в настоящем времени, но рассчете в прошлом. Что плохого будет в противоположном случае?
      Пусть есть игроки A, B и C. А выстрелил в B, но у него большой пинг. B выстрелил в C, его сигнал мгновенно дошел и игрок C умер, что и отобразилось на клиенте. Потом дошел сигнал от A, игрок B умер в прошлом, а значит C ожил. Выглядит как странный лаг.

      Допустим, это не выстрел, а удар в рукопашной с последующей анимацией броска через спину с прогиба. Второго игрока надо телепортировать? «Эй, парень, ты тут уже полсекунды на земле лежишь, нажми кнопку встать!»

      Поэтому обычно такое мощное взаимодействие не делают)

      Глобально правила для многопользовательских игр такие: на один физически объект(положение и вращение) единовременно может влиять не более 1 игрока.
      В противном случае пинг от 50 ощущается просто отвратительно сильно.


  1. SkyMind
    10.06.2016 11:43
    -1

    «Например если хочется разнести врагу бошку!» — ошибочка, слово «башка» через 'а' пишется. Выделено жирным и бросается в глаза.


    1. marsermd
      10.06.2016 11:44

      Спасибо. Обычно для таких уведомлений используются ЛС. У меня вроде и контакты даны если ридонли не могут пользоваться ЛС на хабре)


    1. DrZlodberg
      10.06.2016 12:34
      +1

      Справедливости ради — есть разговорный вариант «разнести бoшку» (с ударением на «о»). Хотя не знаю, на сколько он правилен.


      1. SkyMind
        10.06.2016 22:11
        +1

        Для уверенности (перед тем как написать) проверил поиском в инете. «Башка? — разговорное название головы, заимствовано из тюркских языков: ср. Туркменбаши («глава туркмен»), кызылбаши («красноголовые»).»


        1. marsermd
          10.06.2016 23:18

          Вы все правильно скорректировали, я даже поправил статью) Я думаю, единственное за что вам минус влепили — нарушение традиций хабра.


        1. DrZlodberg
          11.06.2016 08:20

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


  1. saimon108
    10.06.2016 15:03

    Интересно было бы узнать мнение автора о мультиплеерной составляющей игры Dark Souls 3.
    Так большой пинг несомненно является читом.


    1. marsermd
      10.06.2016 15:03

      Увы, не играл и не разбирал мультиплеер DS3)


      1. saimon108
        10.06.2016 15:53
        +1

        Кстати интересный тип мультиплеера — разрабы DS одними из первых стали встраивать мультиплеерные вторжения других игроков в синглеплеер игрока.

        Позже подобный тип мультиплеера пришел в ватч догс и мгс 5.


      1. bromzh
        10.06.2016 16:09

        Ну мультиплееры во всей серии Souls похожи. В целом, там всё тоже самое: если попадается игрок с большим пингом, то часто по тебе проходят удары, которые с твоей точки зрения не должны были до тебя достать, так как ты вышел из зоны действия оружия. Или удар в спину: ты уже стоишь лицом, но тут тебя телепортирюет к позиции врага и срабатывает анимация удара в спину.


        Интересно вот что: там многие игровые значения рассчитываются исходя из FPS. Иногда это выглядит забавно, например, оружие при 60 FPS изнашивается куда быстрее, чем при 30. Вы не знаете, зачем так делается, какие плюсы и минусы у такого подхода и т.д.? Интересно было бы почитать.


        1. marsermd
          10.06.2016 17:04

          О_О привязка к фпс звучит очень странно.
          Все обычно наоборот стараются абстрагироваться от FPS. А чтобы привязывали износ к FPS — это знатный изврат)
          На тему рукопашки. Рукопашный бой — это вообще больная тема. С точки зрения игрока A, A и B находятся рядом, а с точки зрения игрока B, A и B рядом никогда не были. И что тут делать?


          1. Wedmer
            10.06.2016 17:51

            Это изначально консольная игра была. Учитывая, что конкретные модели консоли все одинаковые, то FPS вполне себе был константой.


            1. marsermd
              10.06.2016 18:07

              Да, в этом есть логика. Видимо там в принципе время неправильно рассчитывалось.


              1. Wedmer
                10.06.2016 18:22

                В первой части DS FPS был фиксированым на 30. По сути все неприятности изначально поправили энтузиасты.


          1. bromzh
            10.06.2016 18:56

            Как уже сказали, игра изначально была консольная, так что железо было одинаковым. При низком ФПС на компе отрубается мультиплеер. Так и пишет: "недостаточно кадровой частоты для игры по сети".


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


            1. marsermd
              10.06.2016 19:04

              Это звучит действительно интересно!
              Я на выходных покопаюсь, может найду что-нибудь.