Я создаю свою первую онлайн-игру с использованием socket.io, и мне бы хотелось, чтобы она была многопользовательской игрой в реальном времени, такой как agar.io или diep.io.
Но я столкнулся с проблемой выяснения того, как заставить все компьютеры работать с одинаковой скоростью.
У меня есть три идеи для моделей, но ни одна из них не кажется правильной, и мне интересно, как это делают обычные видеоигры. (Вы можете пропустить чтение моих идей; они просто дают вам возможность увидеть проблемы, с которыми я сталкиваюсь.)
Сервер позволяет клиентам работать самостоятельно и передавать обновления на сервер, который затем передает их остальным клиентам. Это связано с тем, что некоторые компьютеры работают быстрее, чем другие, что позволяет им обновляться быстрее и перемещаться по экрану быстрее.
Пусть сервер скажет клиентам, когда обновлять. Затем я могу дождаться ответа последнего клиента (ужасная идея, если у одного человека медленный компьютер), дождаться ответа первого клиента (опять же, ожидая связи перед каждым кадром) или просто отправить их как можно быстрее (что кажется, сталкивается с той же проблемой, что и номер 1).
В начале игры попросите сервер сообщить клиентам, как быстро выполнить обновление. Это будет означать, что клиент будет нести ответственность за ограничение движения между этими периодами времени. Например, если кому-то каким-то образом удалось нажать кнопку дважды в течение этого периода времени, он отправит только одно событие нажатия кнопки. Это приводит к тому, что некоторые действия будут игнорироваться (например, нажатие двойной кнопки) и что взаимодействие будет зависеть от часов клиента, которые могут не совпадать с часами сервера. Сервер должен будет отслеживать каждого клиента и следить за тем, чтобы его обновления отправлялись в нужное время.
Я провел некоторое исследование , но статьи, которые я читаю, явно не касаются того, что делать, если клиент отправляет обновления быстрее, чем другие клиенты.
В моем конкретном случае я имею дело с людьми, которые имеют более высокие скорости клавиатуры (их компьютер будет отправлять больше обновлений клавиатуры, чем другие компьютеры).
Как программисты обычно справляются с этим?
источник
Ответы:
Ваша третья идея кажется наиболее близкой к тому, что я считаю отраслевым решением для такого рода проблем.
То, что вы описываете, обычно называют клещами . В каждом тике фиксированное число действий будет обрабатываться для каждого клиента последовательно. Часто игровые серверы могут выполнять некоторые параллельные действия, когда это возможно, но это гораздо более сложная проблема.
Тик, вероятно, будет в форме 1 / N секунд, N - количество тиков в секунду, или Tickrate. Этот тикрейт может быть очень, очень часто или очень редким, в зависимости от вашего варианта использования. Мое личное предложение - избегать тикрейта выше 60 тиков в секунду, если вы не уверены, что вам нужно больше. Вы, вероятно, не :)
Действия должны быть атомарными. Например, в slither.io действие, такое как перемещение, не должно немедленно обрабатывать что-то вроде разрыва вашей цепи, если только игрок, которого вы ударили, уже не сделал свой ход. Это может показаться тривиальным для чего-то на уровне пикселей, но если вы имеете дело с движением на основе плиток, это становится намного более очевидным и обеспечивает справедливость. Если игрок A переходит на плитку X, а игрок B в данный момент находится на этой плитке, вы должны убедиться, что к концу такта игрок B все еще будет на этой плитке, чтобы любые действия между ними происходили.
Кроме того, я бы сказал, что не следует выполнять какие-либо вычисления на стороне клиента, если они не выполняются независимо на стороне сервера. Это становится сложным и дорогим с физикой (из-за этого многие игры выбирают более низкий тик по физике, чем многие другие действия и события)
Для справки, вот хорошая ссылка, чтобы дополнить ваше собственное понимание игровых серверов и многопользовательских сетей.
Наконец, я бы сказал, не позволяйте справедливости разрушить ваш сервер. Если есть уязвимости, которые делают вашу игру несправедливой, исправьте это. Если дело в том, что лучший компьютер имеет небольшое преимущество, я бы сказал, что это может быть не так уж важно.
источник
Следующая система гарантирует, что все клиенты и сервер имеют практически одинаковое игровое состояние в любое время.
Иметь состояние игры как на клиенте, так и на сервере.
Когда клиент пытается использовать команду (мышь, клавиатура и т. Д.), Проверьте его состояние игры, если оно действительно.
Если это так, отправьте команду на сервер, не выполняя ее на клиенте-отправителе.
Когда сервер получит команду, посмотрите на ее состояние игры, если она действительна.
Если это так, отправьте команду обратно ВСЕМ клиентам с точной будущей датой, после чего ее выполнение должно быть завершено на сервере, затем выполните действия, запрошенные командой, после задержки, равной минимальному времени для отправки команды клиентам. , затем запишите дату, это поможет сделать прогноз на будущее. Если время меняется слишком сильно, сделайте свою игровую систему более детерминированной.
Когда клиент получает команду от сервера, просмотрите его состояние игры, если оно действительно, немедленно выполните действия, запрошенные командой, затем посмотрите текущую дату и сравните ее с полученным прогнозом даты. Если он недействителен, клиент не синхронизирован. (Все клиенты с похожим соединением получают одновременно)
Если дата раньше, у вас возникла проблема на предыдущем шаге, исправьте ее. Если дата немного позже, ничего не делать. Если дата слишком долгая, клиент не синхронизирован, то есть клиент слишком сильно отстает.
Когда клиент не синхронизирован, запросите копию всего игрового состояния сервера и используйте ее. Если это происходит слишком часто, исправьте это, потому что это дороже, чем отправка команд.
На клиентах выводите материал на экран ТОЛЬКО тогда, когда больше нечего делать. В простых сценариях функция рендеринга принимает в качестве входных данных только текущее состояние игры.
Кроме того, вы можете оптимизировать много, используя прогностические системы, группируя команды, рендеринг только различий и т.д ...
Проверка должна отличаться, например, это зависит от сервера, чтобы ограничить запросы команды / единицу времени.
источник
Я не знаю, является ли это проблемой библиотек или среды, которую вы используете, но я думаю, что вы подходите к этому совершенно неправильно.
В подавляющем большинстве многопользовательских игр только сервер выполняет реальные вычисления. Клиенты - это просто тупые машины ввода-вывода, где только реальная проблема производительности заключается в рисовании 3D-графики. И в этом случае не имеет значения, может ли клиент работать со скоростью 20 или 200 FPS, потому что это влияет только на визуальные эффекты. Это означает, что «обновление клиента» не имеет абсолютно никакого значения. Клиент может попытаться «предсказать», какой сервер может рассчитывать, но это только для сглаживания ощущения игрового процесса и не оказывает реального влияния на сам игровой процесс.
Я даже не знаю, что это значит. Большинство людей даже не могут идти в ногу со скоростью младших клавиатур, так как это повлияет на производительность игроков?
В противном случае вопрос кажется слишком широким, и вместо этого вам следует сосредоточиться на одной актуальной проблеме, вместо того, чтобы пытаться придумать «общую» проблему, которой у вас может и не быть.
источник