Используют ли хорошие многопользовательские/ммо клиент‹›серверные игры задержку при расчете перемещений?

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

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

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

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

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

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

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

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

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

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


person Tom    schedule 19.09.2009    source источник


Ответы (5)


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

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

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

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

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

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

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

person Jonas B    schedule 19.09.2009
comment
Обратите внимание, что я не спрашиваю, какую систему движения или алгоритм используют многие игры, я обсуждал это в другой теме. Основной вопрос здесь заключается в том, следует ли учитывать задержку при расчетах перемещений (выполняемых либо на стороне клиента, либо на стороне сервера), и верны ли сделанные мной предположения. Проголосуйте за попытку помочь, несмотря ни на что. - person Tom; 20.09.2009
comment
Извините за заблуждение. Мои два цента в том, что вы должны, по крайней мере, использовать компенсацию задержки на стороне сервера, чтобы сделать ее справедливой для людей с высокой задержкой. Однако хороший способ реализовать это не то, на что я мог бы ответить. Удачи, и я надеюсь, что вы найдете то, что вы ищете в конце концов. - person Jonas B; 20.09.2009

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

Да, задержка всегда полезна в расчетах. Но это немного сложнее, чем 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+differeltaT. Он не может изменить то, что он уже симулировал, поэтому, если он не откладывает симуляцию, он прыгнет на удаленный корабль, и вы увидите рывковый кадр. Вот почему моделирование кораблей с дистанционным управлением должно происходить с задержкой на время, постоянно превышающее 2*типичная дельтаТ. Это должна быть постоянная задержка или задержка, которая меняется постепенно, и во время серьезных задержек вы все равно увидите рывки кадров.

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

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

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

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

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

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

Удачи.

person Mike Dilger    schedule 18.10.2010

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

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

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

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

person aaron    schedule 28.09.2009
comment
таким образом, сервер должен всегда знать время приема-передачи клиента? Кроме того, как бы вы сохранили X, Y и угол каждого корабля в каждый момент времени? И как бы вы рассчитали это, если корабль тем временем вращался? - person Tom; 29.09.2009
comment
Задержка не имеет значения, потому что клиент и сервер пересылают симуляцию в общий период времени. поэтому, если клиент говорит «в момент 5 я прыгнул», сервер может правильно смоделировать это событие в момент 5. Q2: Для хранения данных: просто создайте несколько копий. По сравнению с вашей информацией о сетке или игровыми данными, ваша динамическая информация ничтожно мала. Q3: Детерминизм и разрешение конфликтов. сим вперед во времени. Если игроки A и B взаимодействуют, разрешите и исправьте клиентов. если нет конфликта: сервер и клиент автоматически синхронизируются. - person aaron; 06.10.2009

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

person liyonghelpme    schedule 17.11.2017

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

person Cem Kalyoncu    schedule 19.09.2009
comment
Я делаю именно это. Однако эта проблема связана с позицией других игроков вокруг, а не с вами. - person Tom; 19.09.2009