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


Предлагаю вашему вниманию перевод статьи Fast-Paced Multiplayer (Part I): Introduction.

Разработка игры — само по себе непростое занятие. Но мультиплеерные игры создают совершенно новые проблемы, требующие разрешения. Забавно, что у наших проблем всего две причины: человеческая натура и законы физики. Законы физики привнесут проблемы из области теории относительности, а человеческая натура не даст нам доверять сообщениям с клиента.

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

Часть I


Проблема читерства


Вся наша головная боль начинается с читерства.

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

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

Есть много вещей которые можно сделать чтобы предотвратить читерство. Но самый главный принцип(и наверное самый глубокий) очень прост: не доверяй игроку. Всегда ожидайте худшего — что игрок будет пытаться вас обмануть.

Авторитарный сервер и наивный клиент


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

Конечно, сервер может быть взломан, но эта тема выходит за рамки данной серии статей. Тем не менее, использование авторитарного сервера предотвращает широкий спектр читов. Например, вы не можете доверять клиенту уровень жизней игрока. Взломанный клиент может изменить локальную информацию и сообщить что у игрока 100000% жизней, но сервер знает что жизней всего 10% и если игрока атакуют, он умрет вне зависимости от того, что об этом думает клиент.

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

— Я на (10, 10)
А секундой позже:

— Я на (20, 10)

При этом возможно он «прошел» через стену или двигается быстрее чем ему положено.

А вот правильная парадигма. Сервер знает что игрок находится в позиции (10, 10); клиент говорит: «Я хочу подвинуться на единицу вправо». Сервер обновляет позицию игрока на (11, 10), производя все необходимые проверки, а затем отвечает игроку: «Вы на (11, 10)»:





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

Разбираемся с сетями


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

Давайте поговорим о физике. Предположим что вы находитесь в Сан-Франциско и подключаетесь к серверу в Нью-Йорке. Это примерно 4000 километров. Так как ничто не может передвигаться быстрее скорости света, в лучшем случае сигнал дойдет за 13 миллисекунд. Но весьма маловероятно, что у вас будет такая хорошая связь. В реальном мире информация не идет прямым путем, причем не со скоростью света.
Так что давайте предположим, что это занимает 50 мс. И это практически лучший сценарий. А что если вы подключаетесь к серверу в Токио? А что если линия связи перегружена? В таких случаях задержки доходят до половины секунды.

Вернемся к нашему примеру. Пусть клиент отправляет сообщение:

— Я нажал на стрелку вправо.

Сервер получает запрос через 50 мс и сразу отправляет обратно обновленное состояние.

— Вы на (11, 10)

Это сообщение дойдет до пользователя еще через 50 мс.

С точки зрения игрока, он нажал на стрелку, потом 0.1 секунды ничего не происходило, а затем персонаж наконец подвинулся на единицу вправо. Этот лаг между командой и её результатом может показаться незначительным, но он заметен. И уж конечно лаг в полсекунды был бы не просто заметным, а сделал бы игру абсолютно неиграбельной.



Резюмируя


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

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


Часть II


Введение


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



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

Предсказание на стороне клиента


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

Мы можем использовать это если игра достаточно детермениртована (то есть результат определен командами и предыдущим состоянием).

Предположим что у нас лаг 100 мс и время перемещения персонажа составляет 100 мс. При использовании наивной реализации, время действия составит 200 мс.



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

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



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

Проблемы синхронизации


В предыдущем примере я аккуратно подобрал числа чтобы все отлично работало. Давайте немного изменим сценарий. Лаг будет составлять 250 мс, а анимация передвижения на одну единицу будет длиться 100 мс. А еще давайте игрок дважды быстро нажмет на стрелку вправо.

При использовании текущего подхода вот что произойдет:



Мы столкнулись с интересной проблемой на t = 250 мс, когда нам пришло новое состояние. Клиент предсказал x = 12, но сервер говорит что x = 11. Так как сервер авторитарный, клиент должен передвинуть персонажа обратно на x = 11. Но позже, на t = 350, сервер говорит что x = 12, так что персонаж опять прыгает, но на этот раз вперед.

С точки зрения игрока, он нажал на стрелку вправо дважды, так что персонаж переместился на две единицы вправо, постоял там 50 мс, прыгнул на единицу влево, постоял там 100 мс и прыгнул на единицу вправо. Конечно, это совершенно неприемлимо.



Согласование с сервером


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

Но обойти эту проблему не так уж сложно. Давайте будем добавлять к каждому запросу от клиента его номер. А сервер при ответе будет добавлять номер последнего обработанного запроса. И давайте хранить на клиенте копию всех команд, отправляемых на сервер.



Итак, на t = 250 клиенту приходит «x = 11, последняя команда #1». Клиент удаляет все команды до #1 включительно, но оставляет копию #2, о которой еще не знает сервер. Он применяет полученное от сервера состояние (x = 11), а затем применяет ввод, который еще не виден серверу. В данном случае #2 «вправо на 1 единицу». Конечный результат x = 12, что соответствует истине.

Далее, на t=350, от сервера приходит новое состояние: «x = 12, последняя команда #2». Клиент удаляет все копии команд до #2 включительно, а затем применяет состояние x=12(ничего не изменилось). Так как более нет необработанных команд, на этом все заканчивается, с корректным результатом.



Итоги


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

Но не стоит на самом деле обновлять жизни персонажа, пока сервер не пришлет обновленное состояние.

Из-за сложностей игрового состояния, которое не всегда легко откатить, возможно не стоит убивать персонажа даже если уровень его жизни упал ниже нуля. Что если что другой игрок вылечился прямо перед вашей атакой, но сервер еще об этом не сообщил?

Прим. перев. Я бы убивал персонажа сразу, но обеспечил персистентность(возможность откатывания состояний). Так будет проще писать переносимый код, выполняющийся и на сервере и на клиенте. В любом случае, как вы убедитесь в этом позже, это придется делать.

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

Резюмируя


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

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


  1. Ramazoid
    01.06.2016 17:08
    +3

    Несомненно + ))


  1. imbeat
    01.06.2016 17:12
    +1

    Спасибо, очень интересная статья. О некоторых моментах не знал, но, так скажем, догадывался. Познавательно.
    Интересно было бы узнать статистику, например, сколько запросов в секунду улетает от клиента к серверу в самых популярных онлайн играх (WoT, Dota и тп)?


    1. marsermd
      01.06.2016 17:24
      +5

      Пожалуйста! Еще две статьи на подходе.

      Вот этот потрясающий разработчик иногда разбирает сетевые механики популярных игр.
      Например тут он рассказывает про Overwatch.

      Обновления от сервера к клиенту идут от 20 до 60 раз в секунду обычно. Чем чаще идут обновления — тем комфортней играть, но за счет техник согласования с сервером и локального предсказания, разница между 20 Hz и 60 не очень заметна, а нагрузка на сервера очевидно возрастает.


      1. 6opoDuJIo
        01.06.2016 17:27
        +1

        Вы не поймёте что такое по-настоящему быстрая игра, пока не поиграете по сети в Rocket league. Поверьте: здесь чувствуется даже пинг в 50.


        1. marsermd
          01.06.2016 17:34

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


          1. 6opoDuJIo
            01.06.2016 18:09

            Локально всё применяется, просто если разница между разными игроками даже в 15 мс, это заметно: мяч может внезапно поменять траекторию прямо в воздухе. Или ты сам.


            1. marsermd
              01.06.2016 18:18

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


              1. 6opoDuJIo
                02.06.2016 00:44

                Прекрасно понимаю, но фрустрация от этого не уменьшается.


        1. turbo_exe
          01.06.2016 20:11
          +1

          могу ещё посоветовать поиграть в q3. там за время пока ты делаешь rocket-jump, противник успевает появиться на экране, сожрать power-up, на который ты делаешь rocket-jump и ускакать дальше.


          1. 2PAE
            02.06.2016 06:53
            +2

            Это вы батенька в Q1 не играли. :) Там даже в локалке у того кто сидел на сервере было преимущество.
            Поэтому приличные люди, у нас, на сервере не играли. Или садили за эту машину самого слабого игрока. Дабы уровнять шансы.


        1. Miraage
          01.06.2016 23:25
          +1

          Во всех FPS играх решают даже 10ms. А один из лучших игроков в League of Legends — SKT Faker, сказал, что несмотря на то, что это MOBA жанр, играть в нее с пингом выше обычного (они в корее играют с пингом 5-7) = ад.


          1. 6opoDuJIo
            02.06.2016 00:43

            Дело даже не в жанре мобы, а в специфике лола: скорость поворота персонажа довольно высокая, поэтому отклик сильно чувствуется.


            1. Ydjeen
              03.06.2016 15:44
              +2

              Вероятно вы путаете LoL и Dota2.
              В лоле скорость поворота отсутствует — юнит разворачивается на 180° моментально. В Dota2 они важны, можно ознакомиться в этой статье: http://dota2.gamepedia.com/Turn_rate


              1. saboteur_kiev
                06.06.2016 01:10

                Тем не менее в любой интерактивной хардкорной игре, вполне различаются 10-20 мс.

                Да даже взять некогда существовавший отличный портал тетрисарена.
                Двое игроков играют друг с другом в тетрис. Лаг в 50 милисекунд — это просто нереально играть для игроков, наигравших 5-7 тысяч дуэлей.


        1. saboteur_kiev
          02.06.2016 10:21

          «даже в 50»
          В контерстрайке 50 давным давно считается слишком плохо, И различается 20-30.

          Есть даже соло игры, где при лаге в 50 мс вообще играть практически невозможно.


      1. lain8dono
        01.06.2016 21:57

        Gaffer on Games

        Вот переводы его статей я бы почитал. (Особенно тех, которые закрыты.)


      1. gresolio
        02.06.2016 11:40

        Спасибо за ссылку на Overwatch Netcode Analysis, не видел раньше, у автора также много других полезных видео, понравились.
        Одна только маленькая поправка: Chris aka Battle(non)sense != Glenn Fiedler aka Gaffer on Games. Это разные люди. В этом легко убедится если загуглить например GDC видео с Glenn Fiedler-ом, а затем посмотреть любой «netcode analysis» от Chris-a :)

        Кстати статьи Gaffer on Games очень толковые, некоторые уже стали почти классикой) Можно также подумать о переводе, например «Fix Your Timestep!» или «Networked Physics (2004)» — для которой есть потрясающая демка с исходниками на сишке: управляем кубом, симуляцию физики которого можно смотреть в трёх представлениях: клиент, сервер, прокси (регулируются такие параметры как "% packet loss" и «milliseconds latency»).


        1. marsermd
          02.06.2016 11:41

          Спасибо большое. Я видимо запутался из-за того что Глен запостил это видео в своем блоге.


  1. Duduka
    01.06.2016 17:30

    Осталось понять как остальным клиентам предсказывать действия первого клиента и сервера с протоколом, и что же отрисовывать?! Вы не указали механизм описания транзакции в протоколе, как результат «событие» "развалилось" на независимые, и каждый актор получит собственную историю, иногда это хорошо, но не всегда-же, иногда коллективное взаимодействие — часть игрового процесса.


    1. marsermd
      01.06.2016 17:34

      Это будет описано как раз в следующей статье. Следите за обновлениями)


      1. Evengard
        01.06.2016 17:43

        Жду с нетерпением, в этой статье описанное достаточно логично и предсказуемо, но вот этот факт тоже очень сильно интересует.


        1. marsermd
          01.06.2016 17:51

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


          1. tobolenok
            01.06.2016 18:18

            Чтобы сократить пинг Игрок1-Сервер-Игрок2, пора бы придумать torrent сессии между игроками.
            Чуть сложнее, но те же принципы предсказания и проверок на состояние могли бы скрасить ситуацию.
            Необязательно всех-со-всеми, существуют локальные зоны, в которых находятся игроки.


            1. marsermd
              01.06.2016 18:20
              +1

              Т.е. отправлять команды не только на сервер, но и другим игрокам? Забавно.
              Но есть несколько проблем.
              Основная проблема, как мне кажется, в ненадежности клиента — он может на сервер отправлять одни команды, а игрокам — другие, тем самым усложняя задачу своим соперникам.
              Есть и еще проблемы. Например, компенсация лага, о которой я буду говорить в четвертой статье, будет неприменима в такой игре.


              1. tobolenok
                01.06.2016 18:25

                Сервер сравнил команды. Не совпали? Сразу бан.
                А то получается большая часть работы чтобы противостоять жуликам.
                Хотя весь мир построен на этом.

                С интересом жду следующей части. Спасибо!


                1. marsermd
                  01.06.2016 18:40
                  +4

                  А с чем серверу сравнивать команды? Пересылать их от других клиентов серверу и сравнивать показания?)
                  Не сложно понять, что количество запросов на сервер будет возрастать квадратично. Да и нельзя верить командам от других клиентов.

                  Ждите!)


                  1. tobolenok
                    01.06.2016 18:54
                    +1

                    Было одно секретное место, где вмногером можно было играть без лагов.
                    Клуб в подвале.
                    Деньги платились именно за это.


                  1. Darth_Malok
                    03.06.2016 15:44

                    А если верить клиентам, но потом за ними перепроверять? Например, если игрок говорит, что прошёл сквозь стену, верить ему, а уже потом, «не торопясь», всё проверить. Если что-то подозрительное — банить. Примерно так работают некоторые самописные античиты в minecraft. Но нагрузка на сервер возрастает, конечно.


                    1. saboteur_kiev
                      06.06.2016 01:11

                      Кого из двух банить?
                      А если заглючил сам сервер, или глюк в текстурах?


              1. 2PAE
                02.06.2016 07:05

                Концепция разнесенного на клиенты сервера? Кластер состоящий из компьютеров игроков? Да, на вскидку это сложно.
                И вроде никто ещё так не делал в играх.

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

                Но как-то же кластеры распределенных вычислений между собой договариваются?

                Есть и еще проблемы. Например, компенсация лага, о которой я буду говорить в четвертой статье, будет неприменима в такой игре.

                Это да, подобная система, конечно потребует новых решений известных проблем.


                1. zeronice
                  03.06.2016 15:45
                  +1

                  такая схема приведет к еще большему соревнованию за хороший канал и половина игроков с худшим каналом всегда будет проигрывать


                1. mayorovp
                  03.06.2016 15:57

                  Концепция разнесенного на клиенты сервера? Кластер состоящий из компьютеров игроков? Да, на вскидку это сложно.
                  И вроде никто ещё так не делал в играх.

                  Вообще-то, это стандартное решение в стратегиях, где число юнитов на несколько порядков превышает число игроков.


                  1. marsermd
                    03.06.2016 17:55

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


                    1. mayorovp
                      03.06.2016 19:02
                      +1

                      Все просто — все команды, отданные удаленными игроками, валидируются наравне с командами от локального игрока. Попытка читерить просто приводит к тому, что читер в итоге играет не в ту игру, что остальные. Или выкидывается при сравнении контрольных сумм состояния мира.


                      Единственный чит, который вообще возможен в такой схеме — это "мапхак", снятие тумана войны. Мапхак — это принципиальная уязвимость такого подхода. Каждый клиент знает полное состояние мира — и кто-нибудь всегда найдет способ его "вытащить" и показать игроку.


                      1. Duduka
                        04.06.2016 05:58
                        -1

                        Даже последнее не возможно в «правильном протоколе». Снятие тумана будет читом только, если это позволит получить информацию недоступную при его наличии, т.е., если сервер настолько «туп», что сливает информацию без верификации и проверки прав; так же проблема телепортации и читерского дропа — это только проблема заоптимизации «сервера», предоставляющего права клиенту указывать где, кто и что делает.
                        Можно «заоптимизировать» верификацию, предоставив, Частично, распределенной сети пользователей, но окончательный результат должен быть отработан на серверах, и выдача/раздача бонусов должна осуществляться по итогам этой верификации.

                        Мультиплеер в ММОРПГ, по своей сути, вариант репликации распределенной базы данных на геораспределенной сети. И, где-то, сравним с работой банковского клиента(за исключением того, что последний работает в парадигме клиент-сервер, а нужно сервер-репликанты), и цели похожи, доступ к валюте/игровым бонусам. В связи с чем меня сильно удивляют результаты работы играделов (как корейских, так и китайских), обычно они хранят и раздают не ту информацию, которая нужна в игре, а ту, которая необходима «клиенту» для визуализации игрового процесса, например координаты игрока в городе, пока город пуст(по утрам), с этим еще мирится можно, но во время «флешмоба»!? Или во время осады, зачем мне приходят действия «зевак» в области где ПК запрещены, и во время эвента на котором они участвовать не могут(итак респаун мобов запредельный для «клиента», а тут еще и «зевак» пол сервера)!? Еще один баг-фича централизованной системы — обязательный рестарт Мира, закрытие всех подвисших транзакций, респаун «сбежавших» мобов, обновление магазинов… т.е. все это должно храниться! пока персов несколько десятков в игре эти действия не столь заметны, но прерваный гринд, или сообщение «игра будет остановлена для обновления через 180 секунд» положительных эмоций не оставляет. А нужно-то только обеспечения целостность транзакции «события», не нужны хранение толпы мобов, которые не участвуют в «событии» (а тем более по уровню не подходящие, но отсеиваемые SQL запросом), и репликация данных «по клиентам», если они не имеют никаких отношений к ним, в том числе, если скрыты «туманом», или находятся за пределом достижимости (не инициированные квестом мобы).


                        1. mayorovp
                          04.06.2016 09:34

                          Кажется, вы забыли, что мы разговаривали вот об этой ситуации:


                          Концепция разнесенного на клиенты сервера? Кластер состоящий из компьютеров игроков?


                          1. Duduka
                            04.06.2016 10:25
                            -1

                            Перечитайте еще раз, это ответ именно на этот вопрос. Базу можно хранить в облаке — доверять ей — нет(блокчейн). Событие можно размещать в сети(и нужно, оно там и происходит), но раздача бонусов, в само событие, не входит, и требует некоторой централизации, все остальное — не принципиально. (еще большее разжевывание тривиальных фраз, уже, для меня проблемотично, куда еще проще?! может прежде, чем комменировать, попытаетесь сменить позицию с «оппонент — идиот» на «я был очень невнимателен, и чего-то захотел не понять»)


                            1. qw1
                              05.06.2016 12:45
                              +1

                              Блокчейн — это когда у каждого клиента полная копия всей информации. Как с его помощью наводить «туман войны»?


              1. Duduka
                02.06.2016 10:36
                -1

                Но есть несколько проблем.

                Про это я и говорю, Вы создали проблему, и героически ее решаете…
                «Событие», это не то, что подтвердил сервер, а то что создали игроки, сервер может выдать «приз» или забанить, но он не часть транзакции, он арбитр, полководец…
                Если религия позволяет, то посмотрите на ютубах (у гоблина в Разведопрос) беседы с Климом Жуковым про средневековые битвы. (в вашем случае, вывод по координации битв: правильно построил войска, предугадал действия противника — выиграл, если что-то пошло не так, то скоординировать в этой мясорубке ничего нельзя, поняли отряды изменившуюся обстановку — вырулили ситуацию, нет — драпанули или полегли).

                Как мне видится решение: сервер — арбитр(а не актор), все игроки должны видить единую картину, т.е. сервер обеспечивает функцию прокси и регистрацию действий игроков, а как устраитель ловушек и генератор события предлагает ситуацию, загоняя читеров в уникальные, жесткие или безвыходные ситуации. Игроки (полноценные акторы, в том числе и читоры) должны стоять в равных условиях (транзакция корректирует ( выравнивая ) общую задержку, детектирование читера должно сливать всю пати игрой, а не «только баном», педагогика братья! не в наказании виновных[это правосудие], а в воспитании «законопослушного гражданина»</сарказм>).
                После «события» сервер анализирует лог, и если не находит криминала выдает награды… в том чисте и экспу. Чем это может навредить, и зачем усложнять «на ровном месте»!?


            1. Gri3ly
              01.06.2016 20:44

              вообще P2P в играх используется достаточно давно, правда как правило всё равно присутствует сервер на котором хранится нужная информация.


            1. Rast1234
              01.06.2016 23:02

              Если клиенты будут принимать решения на основе данных от других, обмениваясь при этом с сервером для подтверждения правильности, серверу придется решать кому доверять, а кому — нет. Чем-то на похоже на проблему византийских генералов, в обратную сторону. Ну и получится, что трафик между всеми возрастает, это надо как-то решать. Хотя интересно.


            1. saboteur_kiev
              02.06.2016 10:45
              +1

              Обычно предполагается, что сервер способен обеспечить достаточную пропускную способность.
              Передавать что-либо другим игрокам — гиблая затея.
              Потому что подключение других игроков никак не гарантировано.
              Зайдет в зону игрок с модема, и у всех резко лаги начались?


        1. Ravager
          01.06.2016 17:56
          +1

          да и в след. статье тоже логично и предсказуемо. до тех пор, пока не начнешь это реализовывать ;)


    1. Noiwex
      01.06.2016 20:29

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


      1. marsermd
        01.06.2016 20:30

        Да, если коротко, так оно и происходит.


  1. marsermd
    01.06.2016 17:37

    Оффтоп: а что делать если случайно отклонил комментарий? Есть возможность его вернуть?


    1. myxo
      01.06.2016 17:47
      +1

      Если я не ошибаюсь, то этот коммент ещё прочитает модератор, так что он может вернуть.


  1. Aionoff
    01.06.2016 17:37

    Спасибо! Было бы так же интересно по читать как подобные механизмы реализованы в популярных сетевых фреймворках.


    1. marsermd
      01.06.2016 17:40

      Если с английским все в порядке, советую взглянуть на разработчика о котором я говорил вот тут
      https://habrahabr.ru/post/302394/#comment_9638810


  1. Ravager
    01.06.2016 17:54
    +1

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


    1. marsermd
      01.06.2016 17:59

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

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


      1. Ravager
        01.06.2016 18:22

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


        1. marsermd
          01.06.2016 18:24

          Это правда. И такая ситуация действительно выглядит нечестной для убитого игрока. Но это максимум честности, который только можно предоставить. Думаю, вы в этом убедитесь в четвертой статье.


          1. Saffron
            02.06.2016 11:50

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

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


        1. Rast1234
          01.06.2016 23:04

          Захотелось сдлать игру, намеренно основанную на такой безумной механике %)


          1. IvaYan
            02.06.2016 12:06

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


            Если игрок находится в другом времени, то за него играет ИИ.


            Но как ни стараюсь, я не могу вспомнить названия игры, это было лет 10-12 назад минимум.


            1. Flex1024
              04.06.2016 17:24

              Achron явно не такая старая, но под описание очень сильно подходит. Механика там примерно такая же.


  1. sheknitrtch
    01.06.2016 18:02

    К стати, предсказание на стороне клиент (client-side prediction) было реализовано в QuakeWorld в далёком 1998 году. С тех пор, как видно, революционных изменений не произошло.


    1. marsermd
      01.06.2016 18:23
      +2

      Это просто только первые статьи из серий. Конечно же тут покрываются только самые базовые техники.
      Но решений пространственно-временного парадокса действительно не так уж и много. Хотя простора для локальных улучшений просто тьма)


      1. 2PAE
        02.06.2016 07:15
        +4

        Но решений пространственно-временного парадокса

        Чёрт, я один начинаю оглыдваться по сторонам и вспоминать всякие необъяснимые вещи?
        Бермудский треугольник, пропадание людей и т.п.
        Может всё просто? Есть в мире места где просто пинг, до главного сервера, длинный и текстуры плохо проверенны? Вот люди и исчезают? :)

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


  1. snuk182
    01.06.2016 18:40
    +1

    Мне как разработчику энтерпрайз-приложений особенно интересно читать про внутренности геймдева, там ведь вообще все по другому. Читал эту штуку в оригинале, с удовольствием прочту и перевод, спасибо!


    1. marsermd
      01.06.2016 18:41
      +1

      Да, у нас действительно совсем другая кухня:) За то и люблю геймдев.


      1. Evengard
        01.06.2016 18:56

        Хотелось бы уйти в такой «серьёзный» геймдев… Только такое ощущение что туда ещё фиг прорвёшься :) А «мобилочный» геймдев это вообще не то :(


        1. solver
          01.06.2016 21:53

          > А «мобилочный» геймдев это вообще не то :(

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


        1. marsermd
          01.06.2016 21:59
          +2

          Вы знаете, у нас пока что был мобильный геймдев. И могу вам сказать, что он ВЕСЬМА серьезный)
          Все зависит от компании.


        1. 6opoDuJIo
          02.06.2016 00:47
          +1

          Учите плюсцы, нативный opengl/unreal.
          Потом вперёд на gamedevmap.com.
          Заодно можно с трактора смахнуть пыль.


          1. creker
            02.06.2016 01:01
            +1

            OpenGL мало в геймдеве поможет


            1. TheShock
              02.06.2016 03:00

              Почему вдруг?


              1. lain8dono
                02.06.2016 03:58

                Может по той причине, что gl это всего навсего способ вывода для 2D/3D, но не более.
                Сеть, физика, звук, графика всего лишь относительно низкоуровневые инструменты. По мимо этого есть достаточно много других проблем, которые не менее важны. Часть из них вообще находятся в пределах влияния гуманитариев.


                1. TheShock
                  02.06.2016 04:52
                  +1

                  Ну так кто-то графику, кто-то звук пишет, а кто-то текст. ААА игра ж не одним человеком делается то.


            1. 6opoDuJIo
              08.06.2016 07:05

              Во многих вакансиях затребован пресловутый directx/opengl, а вот phys-x не наблюдал в требованиях к кандидату ни разу.


  1. Sergey-From-Irkutsk
    01.06.2016 19:08
    -1

    +


  1. Scratch
    01.06.2016 19:17
    +1

    Всегда было интересно как работает по сети Q3, динамичней игр я не встречал


    1. Ayahuaska
      01.06.2016 20:05
      +3

      Как-то так: https://github.com/id-Software/Quake-III-Arena


  1. ese
    01.06.2016 19:23
    +1

    Когда занимался разработкой сетевого шутера эта статья помогла разобраться в основах интерполяции и лаго-компенсации.


    1. marsermd
      01.06.2016 20:30

      Да, это великолепная статья. Тоже читал её.


  1. AllexIn
    01.06.2016 19:51
    +1

    Представленная схема с отбрасыванием ИМХО не совсем годится для движения и аналогичных параметров.

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

    Пример: гоночная игра. траетория машин штука сложная, а скорости канала не хватает чтобы более менее в реальном времени отображать позицию.
    Текущий кадр: машина другого игрока совершает поворот. Известна скорость, известна позиция, известен выворот колес. Мы экстраполируем состояние машины, пока не придут новые данные с сервера. Проблема в том, что в гонках идет постоянное подруливание. То есть выворот колес меняется постоянно, в несколько раз чаще чем кадры приходят.
    Очевидно, что наша экстраполяция не будет корректной вообще никогда. Что делать? Экстраполировать как получается, а между кадрами плавно разницу между экстраполированным и реальным значением сглаживать. Просто плавно смещая машину в сторону для компенсации ошибки.
    Если приглядется, то это дает артефакт в виде бокового движения автомобиля. Но на практике заметить это невозможно.

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


    1. marsermd
      01.06.2016 20:39

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

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


      1. AllexIn
        01.06.2016 21:15

        А с ГГ все тоже самое. Не надо его прыжком двигать в точку синхронизации. Просто в процессе движения корректируем ошибку. Прыжок, только если расхождение значительное.


      1. AllexIn
        01.06.2016 21:19

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


        1. meiciuc
          08.06.2016 11:19

          на разных клиентах могут быть (и будут) разные расхождения. Поэтому последняя инстанция, похоже — это все-таки сервер. Вместо того, чтоб на сервере сместить игрока на полметра, Можно на клиенте подкорректировать позицию персонажа. И чтоб не было «скачка», надо попытаться сдвинуть его «естественно». Если движется — скорректировать скорость перемещения. Если уже стоит — пусть сделает шаг в нужную сторону. Статья http://www.gamasutra.com/view/feature/131638/dead_reckoning_latency_hiding_for_.php — для меня в свое время была отправной точкой при разработке мультиплеера.


    1. Tujh
      08.06.2016 11:43

      Вы WoT расскажите про не критичность позиции и точки прицеливания :) Хотя у меня давно есть подозрение, что там очень много корректировок по этому поводу в зависимости от игрока, иногда реально «не пробил» в упор и слабое место, а иногда полный урон в самую толстую броню :)
      Ещё есть много шуток про «Сурвариум», где тоже с позициями игроков всё плохо, «урон не прошёл» — просто бич игры.


  1. dimamir999
    01.06.2016 20:39

    Очень интеренсо) А посоветуйте плз более детальную инфу по этому вопросу может книга или форум разработчиков какойто игры ато в статьях обычно только базовое описано


    1. marsermd
      01.06.2016 20:40

      Если у вас все в порядке с английским, прочитайте комментарии. Тут было дано немало полезных ссылок.
      Если же английский для вас проблема — подписывайтесь на меня и ждите дальнейших статей:)


    1. AllexIn
      01.06.2016 20:41

      Погуглите инфу, как в Source сделана сеть. Там достаточно подробно всё разобрано, на примерах CS, если не ошибаюсь.


  1. Rast1234
    01.06.2016 23:15

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


    1. valera5505
      02.06.2016 00:38

      В Battlefield физика синхронизируется.


    1. marsermd
      02.06.2016 11:51

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

      Впрочем, если воздействие на колесо это действие «взорвать машину», это вполне можно синхронизировать.
      А вот гильзы хоть и можно синхронизировать, так делать не стоит. Это только засорит трафик.


    1. Tujh
      08.06.2016 11:46

      Обычно игровые объекты, влияющие на процесс синхронизируются, а гильзы, пыль, следы от колёс/выстрелов и прочие красоты, которые пропадают через 10-15 секунд отрисовываются только клиентом для зрелищности. Это если говорить про правильную игру :)


  1. vladbarcelo
    02.06.2016 08:00

    Спасибо за статью. Сразу вспомнилось, как в GTA SA-MP ценили людей, обладавших особым навыком «стрельбы по пингу», потому как особенности клиент-серверного общения позволяли людям с пингом больше 1000 начать буквально телепортироваться вокруг другого пользователя за счёт быстрой смены направления бега, которая как раз до сервера вовремя не долетала.


    1. DarkByte
      02.06.2016 08:55

      SA-MP это наверное совсем отдельная тема, ведь там мультиплеер прикрутили к игре, которая не планировала быть сетевой. Кстати проблему с читерами на своём сервере решил кардинально — для подключения к серверу требовалось скачать кастомный клинет, который проверял целостность игровых файлов, защищал память процесса игры от внедрения чужих потоков и предотвращал все попытки её изменения извне. Конечно же и такой античит можно было обойти, но отсутствие готовых решений типа «скачай тренер и запусти» избавило сервер от набегов нечестных игроков.


  1. ProX_Alex
    02.06.2016 11:53
    -1

    Будет ли примеры с кодом в следующих частях? Было бы очень хорошо. И будут ли примеры каких либо не FPS мультиплееров типа La2, WoW и др, как там сервер обрабатывает мир и решает кому что показывать.


  1. srs2k
    02.06.2016 13:42

    У меня вопрос, в большей степени касающийся техники античита — используются ли сейчас в каких-нибудь онлайн играх механики отложенной или «ленивой» проверки корректности действий и перемещений игрока? Я поясню свой вопрос примером:
    Допустим, играет какой-то бессовестный человечек в Батлу, Контру или что-то подобное, при этом использует чит с функциями аимбота, воллхака, проход сквозь препятствия. Дотошные проверки в реальном времени (мог ли игрок попасть в другого со своей позиции, не было ли непроходимых препятствий на пути его движения или траектории выстрела и т.п.) потребуют слишком больших вычислительных ресурсов и замедлят ответ сервера.
    Вопрос: можно ли ли сохранять всю хронику событий на сервере, условно доверяя клиенту игрока на текущий момент, а ретроспективную симуляцию и анализ проводить не вмешиваясь в текущую игровую сессию?

    P.S. Играю в один MMOFPS шутер и часто замечаю, что периодические обновления, в которых декларируется улучшение/обновление античит-защиты обычно прибавляют лагов и тормозов, а полезного эффекта с гулькин нос. Через пару дней читы обновляются, и на ютубе появляются их новые рекламные ролики.


    1. Duduka
      02.06.2016 15:09
      +2

      P.S. Ни один чит не возможен вне игравого процесса, все баги заложенны в протокол: получение дропа, телепортация, бессмертие… Чтобы убрать чит лаги не нужны, достаточно сменить протокол, лаги же вызваны желанием получить контроль над пользователем, сбор информации, слежение за процессами (для контроля за мультами и левыми программами накручивающими какие-то параметры хранящиеся на «клиенте»), изменениями файлов в клиенте (с целью что-то начитерить), и увеличение трафика собранной информацией, и самое главное — раздувание клиента, за счет «нового» игравого контента, который перестает влезать в память и быстродействие падает… уходя в своп. Лаги часто наблюдаются даже при «толстых» каналах с минимальной загрузкой, причем утилизация процессора/ядер доходит до 100% и на длительный срок… в некоторых играх.


    1. Alexander1705
      02.06.2016 16:19

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


  1. dimamir999
    03.06.2016 09:59
    -4

    админ удали случайно написал


  1. DmitryKoterov
    04.06.2016 18:30
    +5

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

    Хуже того: в «реальном» мире нет понятия абсолютной одновременности (события, одновременные в одной системе отсчета, могут быть вовсе не одновременными в другой; см. парадокс шеста и сарая). И контрольный: понятие причинности (событие A могло являться причиной события B) применимо также не для любых двух событий, а только для «времениподобных» — тех, которые произошли, грубо говоря, «достаточно близко» друг от друга (между ними должен успеть пролететь свет; если не успел — то нельзя сказать, какое из них вообще было первое, а какое — второе, потому что существует одна система отсчета, в которой первым было A, и вторая, где первым было B).

    А вы говорите — «геймдев, геймдев». Реальный мир и теория относительности намного круче.


    1. marsermd
      05.06.2016 00:45
      +1

      Не понимаю за что вас заминусили. Если только за оценочный итог.

      Вообще в самом начале статьи и написано, что проблемы идут от вполне реальных физических законов.

      И в этом весь ужас. Надо создать иллюзию классической одновременности для людей, удаленных настолько, что для них бывает только одновременность из СТО.


    1. saboteur_kiev
      06.06.2016 01:14

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


      1. DmitryKoterov
        06.06.2016 02:45
        +2

        Почему вы так думаете? А как же черные дыры и сингулярности? А как же момент большого взрыва и теория струн с 10+ измерениями? Как же квантованность всего вокруг? Как же квантово-волновой дуализм и принцип неопределенности Гейзенберга? Как же квантовая запутанность? По-моему, очень даже глючит он, этот мир, и, по иронии, именно когда соберется много игроков на одной локации, а также когда зум очень уж выкручивают.