Ввод на стороне сервера


9

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

Как правило, это работает очень хорошо, за исключением одной большой проблемы: падение с краев. По сути, если игрок идет к краю, скажем, с обрыва и останавливается прямо перед тем, как сойти с края, иногда через секунду, он будет телепортирован с края. Это связано с тем, что пакет «Я перестал нажимать W» отправляется после того, как сервер обработает информацию.

Вот диаграмма отставания, чтобы помочь вам понять, что я имею в виду: http://i.imgur.com/Prr8K.png

Я мог бы просто посылать пакет «W Pressed» каждый кадр для обработки сервером, но это, казалось бы, было дорогостоящим решением.

Любая помощь приветствуется!

Ответы:


5

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

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

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

Я думаю, что должно произойти, что

client sends a move + position update
server gets it t+latency time later
server verifies and sends out info to all clients
client receives this at (t+latency + latency)

Сложность заключается в том, что если клиент получает сообщение о себе, он в основном должен его игнорировать, если только это сообщение не является чем-то вроде «неверное перемещение, вместо этого перейдите к XYZ». Если это сообщение предназначено для чьего-либо клиента, о котором вы получаете информацию, вам придется вовремя экстраполировать форварды, чтобы оно выглядело примерно так, как оно будет.


Клиент вообще не отправляет свою позицию; это просто предсказывает / интерполирует. Вот почему он падает с краев, когда думает, что он на краю. Кроме того, я не вижу, где я сказал, что задержка составляла 1 секунду, это больше похоже на 8 мс (локальное тестирование) до 100 мс (через Интернет). Я сказал, что игрок возвращается позже, потому что я периодически рассылаю полные обновления позиции. Правильно ли я понимаю, что мне следует отправить позицию, которая, по мнению клиента, должна быть вместе с нажатыми клавишами, а сервер должен проверить, возможно ли это?
Томас

«иногда секунду спустя он будет телепортирован», что подразумевает большие задержки, из-за которых я получил время. В ответной игре «да» клиент играет, а сервер отстает во времени и сообщает клиенту, что он сделал что-то незаконное. Вы заметите, что в многопользовательских онлайн-играх вы в основном видите, как другие люди меняют позиции (которые приходят с сервера), в то время как ваша собственная позиция очень редко отличается от прямых поправок на сервере. Другие люди видят, как вы меняете позицию и т. Д.
Патрик Хьюз

Может ли это все-таки привести к тому, что игрок упадет с края сервера? Если я не отправлю пакет в каждом кадре, сервер все равно может подумать, что проигрыватель движется около 32 мс. (Я отправляю пакеты только каждые три кадра). Или вы предлагаете, чтобы я вообще не имитировал ввод на сервере, а только проверял, находится ли позиция в границах нажатого ввода?
Томас

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

Это очень похоже на то, что я сейчас делаю; отправка позиции на сервер и проверка того, мог ли игрок переместиться в эту позицию. Это, кажется, более эвристический подход, и, по моему мнению, не будет почти эффективным, так как решение сервера, точка. Будет ли отправка меток времени с каждым пакетом? Я думаю, что это искоренит проблему. Я считаю, что Halo и игры, использующие движок Source, используют это.
Томас

0

Я понимаю ваш вопрос как:

Сервер получает пакет, когда я начинаю нажимать кнопку «вперед», и другой пакет, когда я наконец отпускаю кнопку «вперед». Поэтому фактическое движение на сервере начинается и заканчивается примерно на 100 миллисекунд «слишком поздно» в реальной игре по сравнению с тем, что игрок выражает на стороне клиента. Поэтому, если игрок хочет переместиться на 10 секунд, он может переместиться на 10 секунд вместо того, чтобы быть в x >= 1сети.

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

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

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

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


Как я сказал Патрику, я думаю, что решение будет скорее эвристическим; вместо того чтобы сервер был «Человеком», сервер вместо этого проверяет достоверность данных клиента. Это, конечно, должно создать некоторую свободу действий, чтобы лаги или другие проблемы в сети не создавали ложных срабатываний.
Томас
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.