Используются ли в хороших многопользовательских /mmo клиентских <> серверных играх задержки в расчетах движения?

Здесь есть пара вопросов.

Представьте, что у меня есть клиент А, который собирается отправить на сервер следующее сообщение: "НАЧАТЬ ДВИЖЕНИЕ ВПЕРЕД".

Сервер не получит это сообщение мгновенно, так как существует задержка из-за задержки.

Вопрос 1: ping (или лучше: время приема-передачи) - это количество времени, которое требуется клиенту, чтобы отправить сообщение на сервер и получить ответ обратно. Означает ли это следующее, если вы можете игнорировать время, которое требуется серверу, чтобы заметить, что он получил сообщение, и начать отправку ответа (это должно быть очень мало)?

  1. время, необходимое клиенту для отправки чего-либо на сервер = в оба конца / 2
  2. время, которое требуется серверу для отправки чего-либо клиенту = round-trip-time / 2

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

Вопрос 2: должен ли клиент сначала отправить пакет, а затем подождать двустороннее время / 2 миллисекунды, прежде чем фактически выполнить эту команду на стороне клиента (в данном случае: двигаться вперед), чтобы компенсировать задержку / задержку?

Теперь сервер отправит следующее сообщение всем находящимся поблизости игрокам: "КЛИЕНТ А СЕЙЧАС ДВИЖЕТСЯ ВПЕРЕД". Затем эти клиенты будут следить за тем, чтобы характер клиента начал двигаться, и это подводит меня к следующему вопросу.

Вопрос 3: должен ли клиент, получающий сообщение, что другой клиент переехал, принять во внимание, что это сообщение было отправлено сервером в оба конца / 2 миллисекунды назад? Так что текущее время, используемое для временных меток при расчете движения, должно быть уменьшено на время прохождения туда-обратно / 2?

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

5 ответов

Решение

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

Другие клиенты вообще не позволят вам двигаться без ответа от сервера в течение определенного времени. Это то время, когда вы испытываете "зависание".

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

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

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

Конечно, это меняется от двигателя к двигателю, но это довольно общий подход.

Изменить: Забыл добавить, что для сервера очень часто также используется компенсация задержки. Если вы ударите кого-то в mmo, которая находится в пределах вашего досягаемости, этот человек может не оказаться в пределах досягаемости от сервера Таким образом, сервер принимает задержку для обоих ваших клиентов и пытается совпасть, если вы действительно находились рядом друг с другом или нет.

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

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

Локальный клиент, удаленный клиент и сервер предсказывают текущую позицию, используя алгоритмы. Следующие данные близки к типичным:

  • Время: т
  • Размещение: положение (x,y,z) и ориентация (x,y,z,w)
  • Движение: Вектор линейного движения, задающий направление с длиной как скорость (x,y,z), и вектор вращения, задающий ось с длиной как скорость вращения (x,y,z)

Вам нужны алгоритмы, которые экстраполируют из набора [T,P,M] в simtime. Я не буду предоставлять их здесь.

Когда клиент регистрирует изменение на диске корабля в [T,P,M], он не доберется до сервера до T+deltaT. Но если deltaT находится в пределах допустимых задержек в сети, сервер может сказать: "Да, это произошло в T, я принимаю это". В противном случае он может захотеть исправить клиента, сказав: "Нет, это из-за допусков, это произошло в мое время T' ", и в этом случае клиент должен будет ОТМЕНИТЬ все последующие изменения [T,P,M] от исправленного сервером (это означает, что вам нужно сохранить очередь или список из них).

Следующий клиент получит его по адресу T+deltaT+differentdeltaT. Он не может изменить то, что уже имитировал, поэтому, если он не откладывает симуляцию, он прыгнет на удаленный корабль, и вы увидите кадр рывка. Вот почему имитация дистанционно управляемых кораблей должна быть задержана на время, постоянно превышающее 2* типичная дельтаТ. Это должна быть постоянная задержка или задержка, которая постепенно меняется, и во время сильной задержки, тем не менее, вы увидите резкие кадры

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

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

Нет, не откладывайте локальное моделирование, когда перемещается местный "аватар". Казалось бы, слишком безразличным. Вы можете немного задержать его (до 50 мс), чтобы улучшить синхронизацию, но задержка на всем пути к RTT сделает вашу игру разочаровывающе безразличной. Установите опцию для локальной задержки и поиграйте с ней, потому что небольшая последовательная задержка может быть приемлемой и улучшить синхронизацию. Но это не обязательно и может вызвать много проблем, поэтому я рекомендую делать этот код последним. (Если вы пытаетесь сделать FPS-игру ближнего боя, вам нужно будет сделать это и всю другую помощь, которую вы можете получить).

Что касается предотвращения мошенничества и гладкости симуляции: во-первых, клиенты не должны просто экстраполировать последнюю известную позицию, когда меняется официальная позиция. Он должен зарегистрировать корректирующий вектор и медленно перемещаться от старого пути к новому пути для гладкости (но, как я сказал выше, этот код выполняется последним, или он замаскирует другие ошибки). Во-вторых, сервер должен допускать широкий диапазон задержек... даже на машинах в одной и той же сети Ethernet задержка пакетов обычно составляет от 5 мс до 100 мс или около того... это довольно большой диапазон. Конечно, вам нужно отрезать его и сказать: "Если вы говорите, что переехали в момент времени T, но я получил пакет в T + some_large_number, то я думаю, что вы пытаетесь скорректировать прошлое и лгать мне". some_large_number не должен быть намного больше, чем средний RTT, чтобы люди были честными.

Моделирование никогда не будет строго синхронизировано. Они должны оставаться в пределах 400 мс или около того через Интернет, но, безусловно, будут выходить за пределы этого во время задержки... до 30 секунд или более, и вам нужно терпеть такие вещи, потому что они не редкость. Учитывая, что интернет ограничен скоростью света в меди, вы всегда можете ожидать, что задержки в одном направлении обычно находятся в диапазоне не менее 100 мс для ваших удаленных клиентов, часто 500 мс или более.

Поэтому я настоятельно рекомендую вам не пытаться делать FPS-игру ближнего боя через Интернет (некоторые крупные компании пытаются, но всегда будут иметь проблемы). Есть приемы, которые вы можете сделать, если вы используете снаряды (запуская их быстро в одной симуляции и медленно в другой), так что, даже если время выключено, оно выглядит. Кроме того, в FPS-играх используется правило, согласно которому обнаружение удара основано на симуляции атакующих... оно кажется более неправильным, когда злоумышленник знает, что он мертв по цели, и пропускает его, а затем, когда защитник знает, что его сбили с пути, и ему наносят удар. в любом случае. Вы должны выбрать один или другой, и психологически это так, как это было сделано. Для рукопашного боя необходим определенный уровень синхронизации, что, честно говоря, невозможно, и большинство игровых компаний не будут касаться MMORPG FPS в ближнем бою, а будут использовать автоматическое нацеливание (попробуйте поиграть в Mortal Online, вы поймете, что я имею в виду).

Удачи.

Для Q1: это выглядит правильно для меня.

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

В3: клиентам действительно нужно знать, что они моделируют в момент X, а сервер сообщает, что набор событий {A,B,C} происходил в моменты времени {X,Y,Z}. Затем клиент и сервер могут симулировать пересылку с одной и той же информацией и, как правило, оставаться в синхронизации (кроме случаев, когда происходят одновременные конфликты). В этих случаях у вас есть повторная синхронизация с сервером, поэтому вы обычно получаете достаточно узкий предел погрешности и в основном беспроблемную работу.

Если ваша цель - улучшить восприятие латентности, вы также можете просто попытаться довериться клиенту.

Есть несколько сетевых моделей для решения этих проблем;

В сетевой игре вам нужно синхронизировать две вещи: одну - время, другую - пространство.

  1. Модель сетевой игры под названием Lockstep;

Вы должны взглянуть на статью, написанную Age of Empire2 Game Studio, которая описывает детали в модели lockstep.

В этой модели клиент и сервер запускают игровую логику кадр за кадром, например, RTS использует 100 мс в качестве кадра, сервер и клиент синхронизируют Id кадра, что означает синхронизацию времени.

Клиент в кадре 50, отправить команду MoveForward, но не запускать ее немедленно, клиент скажет серверу выполнить команду перемещения в кадре 51; затем, когда приходит кадр 51, сервер и клиент одновременно запускают команду. поэтому логика клиента и сервера будет одинаковой.

В такой модели в кадре 50 клиент и сервер будут запускать команду, выданную, возможно, в кадре 49, поэтому в обратной связи ввода клиента всегда есть задержка в 100 мс или более.

разрыв между клиентом и сервером не только содержит RTT сети, но также содержит задержку логического кадра ,, которая составляет 100 мс;

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

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

  1. другие модели используют синхронизацию состояния

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

когда игрок вводит данные, клиент немедленно перемещается, затем отправляет команду перемещения или целевую позицию клиента на сервер с текущей отметкой времени сервера, которая оценивается клиентом.

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

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

Эти технологии включают в себя прогнозирование клиента, компенсацию отставания сервера inter интерполяцию объекта сервера.

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

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

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

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

Другие вопросы по тегам