Я работаю над 2D-шутером сверху вниз и стараюсь копировать концепции, используемые в сетевых играх, таких как Quake 3.
- У меня есть авторитетный сервер.
- Сервер отправляет снимки клиентам.
- Снимки содержат метку времени и позиции объекта.
- Объекты интерполируются между положениями снимка, поэтому движение выглядит плавным.
- По необходимости, интерполяция сущностей происходит немного «в прошлом», поэтому у нас есть несколько снимков, между которыми можно интерполировать.
Проблема, с которой я сталкиваюсь, это «синхронизация часов».
- Для простоты давайте на мгновение представим, что при передаче пакетов на сервер и с него существует нулевая задержка.
- Если часы сервера на 60 секунд опережают часы клиента, то метка времени снимка будет на 60000 мс впереди локальной метки времени клиента.
- Следовательно, моментальные снимки сущности будут собираться и храниться в течение примерно 60 секунд, прежде чем клиент увидит, что какой-то конкретный объект делает свои ходы, потому что это занимает много времени, чтобы часы клиента успели догнать.
Мне удалось преодолеть это путем вычисления разницы между часами сервера и клиента при каждом получении снимка.
// For simplicity, don't worry about latency for now...
client_server_clock_delta = snapshot.server_timestamp - client_timestamp;
При определении того, как далеко находится объект интерполяции, я просто добавляю разницу к текущему времени клиента. Проблема с этим, однако, заключается в том, что это вызовет дрожание, потому что разница между двумя часами будет резко колебаться из-за того, что моментальные снимки поступают быстрее / медленнее, чем другие.
Как я могу синхронизировать часы достаточно близко, чтобы единственной ощутимой задержкой была та, которая жестко запрограммирована для интерполяции, и та, которая вызвана обычной задержкой в сети?
Другими словами, как я могу предотвратить слишком позднюю или слишком раннюю интерполяцию, когда часы значительно десинхронизированы, без появления рывков?
Редактировать: Согласно Википедии , NTP может использоваться для синхронизации часов через Интернет с точностью до нескольких миллисекунд. Тем не менее, протокол кажется сложным, и, возможно, излишним для использования в играх?
Ответы:
После поисков, кажется, что синхронизация часов двух или более компьютеров не является тривиальной задачей. Протокол, подобный NTP, хорошо работает, но он, предположительно, медленный и слишком сложный, чтобы быть практичным в играх. Кроме того, он использует UDP, который не будет работать для меня, потому что я работаю с веб-сокетами, которые не поддерживают UDP.
Я нашел способ здесь , однако, что , кажется , относительно проста:
Он утверждает, что синхронизирует часы с точностью до 150 мс (или лучше) друг от друга.
Я не знаю, будет ли это достаточно хорошо для моих целей, но я не смог найти более точную альтернативу.
Вот алгоритм, который это обеспечивает:
Это решение, кажется, удовлетворительно отвечает на мой вопрос, потому что оно синхронизирует часы и затем останавливается, позволяя времени течь линейно. В то время как мой первоначальный метод постоянно обновлял часы, заставляя время немного подскочить при получении снимков.
источник
По сути, вы не можете исправить [весь] мир и, в конце концов, вам придется провести черту.
Если сервер и все клиенты имеют одинаковую частоту кадров, им просто нужно синхронизироваться при подключении, а иногда и после него, особенно после события задержки. Задержка не влияет на течение времени или способность ПК измерять его, поэтому во многих случаях вместо интерполяции необходимо экстраполировать. Это создает одинаково нежелательные эффекты, но, опять же, это то, что есть, и вы должны выбрать наименьшее из всех доступных зол.
Учтите, что во многих популярных MMO отстающие игроки визуально очевидны. Если вы видите, что они бегут на месте, прямо в стену, ваш клиент экстраполирует. Когда ваш клиент получит новые данные, игрок (на его клиенте), возможно, переместился на значительное расстояние и будет «резиновым» или телепортироваться в новое место («джерки», о котором вы упоминали?). Это происходит даже в крупных играх известных брендов.
Технически, это проблема сетевой инфраструктуры игрока, а не вашей игры. Точка, в которой он переходит от одного к другому, - это та самая линия, которую вы должны нарисовать. Ваш код на 3 отдельных компьютерах должен более или менее записывать одинаковое количество прошедшего времени. Если вы не получаете обновление, оно не должно влиять на частоту кадров вашей Update (); во всяком случае, это должно быть быстрее, так как, вероятно, меньше обновлений.
«Если у вас плохой интернет, вы не можете играть в эту игру на конкурентной основе».
Это не попутный доллар или ошибка.
источник