Как работать с более быстрыми компьютерами в видеоигре реального времени клиент / сервер

15

Я создаю свою первую онлайн-игру с использованием socket.io, и мне бы хотелось, чтобы она была многопользовательской игрой в реальном времени, такой как agar.io или diep.io.

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

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

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

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

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

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

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

Как программисты обычно справляются с этим?

Pro Q
источник
1
По моему опыту, они этого не делают. Вот почему существуют игровые автоматы; те, кто платит 5 тысяч за современный огнемет, автоматически получают преимущество перед теми, кто все еще использует Commodore 64.
Роберт Харви,
1
Так что мой игровой процесс будет выглядеть медленным, потому что мы должны играть с наименьшим общим знаменателем? Похоже, что игровой сервер должен задавать темп, и клиенты должны идти в ногу, иначе вам придется просто отстать.
Джеффо
3
Возможно, я неправильно понимаю вопрос, но, вероятно, вам нужна модель тикового клиента и сервера. gamedev.stackexchange.com/questions/81608/… По сути, вы только обрабатываете ввод и логику каждые X промежутков времени (обычно 1 / N секунд, например 1/60 для логики 60 Гц)
Кристофер Вирт,
4
После прочтения вопроса, кажется, вы слишком сосредоточены на клиентских аспектах игры. Если вы хотите «честную» многопользовательскую игру, ваш сервер должен быть авторитетным. Это означает, что все, что происходит с клиентами, проверяется или выполняется сервером. Затем вы ограничиваете вещи отсюда, вероятно, через систему, основанную на тиках, как указано выше.
Кристофер Вирт
1
Ах, сетевой код в реальном времени. Самое глубокое, самое темное место разработки игр. Добро пожаловать на корабль, приятель!
Т. Сар - Восстановить Монику

Ответы:

8

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

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

Тик, вероятно, будет в форме 1 / N секунд, N - количество тиков в секунду, или Tickrate. Этот тикрейт может быть очень, очень часто или очень редким, в зависимости от вашего варианта использования. Мое личное предложение - избегать тикрейта выше 60 тиков в секунду, если вы не уверены, что вам нужно больше. Вы, вероятно, не :)

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

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

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

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

Кристофер Вирт
источник
3
@ProQ стоит отметить, что написание хорошего сетевого кода не тривиально! Если ваше приложение с самого начала не работает должным образом, и ваш сетевой код кажется отстойным, не сдавайтесь. Даже люди, которые делают это для повседневной жизни, имеют проблемы с этим. это просто , что трудно!
Т. Сар - Восстановить Монику
0

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

Иметь состояние игры как на клиенте, так и на сервере.

Когда клиент пытается использовать команду (мышь, клавиатура и т. Д.), Проверьте его состояние игры, если оно действительно.

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

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

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

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

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

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

На клиентах выводите материал на экран ТОЛЬКО тогда, когда больше нечего делать. В простых сценариях функция рендеринга принимает в качестве входных данных только текущее состояние игры.

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

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

Валле Кирилл
источник
0

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

В подавляющем большинстве многопользовательских игр только сервер выполняет реальные вычисления. Клиенты - это просто тупые машины ввода-вывода, где только реальная проблема производительности заключается в рисовании 3D-графики. И в этом случае не имеет значения, может ли клиент работать со скоростью 20 или 200 FPS, потому что это влияет только на визуальные эффекты. Это означает, что «обновление клиента» не имеет абсолютно никакого значения. Клиент может попытаться «предсказать», какой сервер может рассчитывать, но это только для сглаживания ощущения игрового процесса и не оказывает реального влияния на сам игровой процесс.

более высокая скорость клавиатуры

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

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

Euphoric
источник
Более высокая скорость клавиатуры - это не набор текста, а количество команд, которые можно отправить, если удерживать клавишу «вперед» или «стрелять».
gbjbaanb
@gbjbaanb И как это проблема? Вы должны заботиться только о нажатых и отпущенных командах. Вы не должны заботиться о том, как быстро его обновить.
Эйфорическая
Вы заботитесь о том, чтобы обрабатывать все события, как ожидалось, на клиенте. Таким образом, если вы нажмете клавишу w, вы продвинетесь на небольшое расстояние, и ваша клавиатура будет быстрее, чем кто-либо другой, вы будете быстрее, чем они. Последнее, что вы хотите, это сделать гоночную игру, в которой вам нужно было нажимать клавишу, чтобы двигаться вперед!
gbjbaanb
@gbjbaanb Нет. Это неправильно. Сервер знает, «игрок идет вперед», и затем каждую 1/60 секунды обновляет позиции ВСЕХ игроков в зависимости от того, идет ли он вперед. Так работают ВСЕ игры. Цикл обновления одинаков для всех объектов в игре, и обновления НЕ основаны на событиях из пользовательского интерфейса.
Эйфорическая
1
Нет, это не то, что понимал ОП, именно поэтому он спросил об этом, и именно поэтому вы сказали: «Я даже не знаю, что это значит». Если вы понимаете позицию ОП, то его вопрос имеет смысл. Если ОП закодировал свою игру для работы с игровым циклом, полностью основываясь на том, как быстро доставляются события от клиента, то это то, о чем он спрашивает - вы ошибаетесь, применяя какой-то гипотетический игровой дизайн к тому, о чем фактически спрашивает ОП, независимо от того, является ли его дизайн неправильным по большинству стандартов.
gbjbaanb