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

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

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

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

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

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

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

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

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

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

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

Ответы [ 5 ]

8 голосов
/ 19 сентября 2009

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

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

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

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

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

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

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

4 голосов
/ 18 октября 2010

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

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

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

  • Время: t
  • Размещение: положение (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, вы поймете, что я имею в виду).

Удачи.

1 голос
/ 29 сентября 2009

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

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

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

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

0 голосов
/ 18 ноября 2017

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

0 голосов
/ 19 сентября 2009

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

...