Я делаю физическую игру с быстрым темпом - настольный хоккей. С двумя молотками и одной шайбой. Игра работает на iphone / ipad, и я делаю многопользовательскую часть через GameCenter.
Так работает сетевая система. Клиент, которому назначено совпадение, будет считаться сервером, а тот, который принимает запрос на совпадение, является клиентом.
На «сервере» запущена физика, и ответ мгновенен, а на клиенте также запущена физика, поэтому он выглядит гладко между обменом сообщениями. Что я делаю в качестве сервера, так это то, что я отправляю клиенту мою скорость шайбы и мою позицию, и клиент регулирует свою скорость / позицию шайбы, связанную с сервером, чтобы поддерживать его синхронизацию. В противном случае физика десинхронизируется и облажается.
Когда сетевая задержка хорошая, ниже 100 мс, результаты довольно хорошие, я получил плавную играбельную игру на стороне клиента, и странное поведение минимально. Проблема возникает, когда задержка составляет от 150 до 200 мс. В этом случае случается, что моя клиентская шайба уже достигла края и перевернутого направления, но получает сообщение о задержке от сервера и немного отступает назад, вызывая странное чувство поведения мяча.
Я прочитал несколько вещей об этом:
Википедия о синхронизации часов
Итак, как я могу решить это? Насколько я прочитал, лучший вариант, который у меня есть, это выполнить синхронизацию часов на сервере / клиенте с отметкой времени, чтобы, когда я получаю сообщения о задержке, связанные с моими часами, я просто игнорировал их и позволял моделированию клиентов выполнять работа. Ребята, вы согласны с этим? И так как я посылаю ненадежные данные (UDP), я могу получить задержанные сообщения или сообщения не в порядке.
Если это лучший подход, как мне реализовать синхронизацию часов. Я прочитал шаги о том, как, но я не совсем понял это.
Это говорит о том, что:
- Клиент маркирует текущее местное время в пакете «запрос времени» и отправляет его на сервер.
- При получении сервером сервер помечает серверное время и возвращает
- После получения клиентом клиент вычитает текущее время из отправленного времени и делит на два для вычисления задержки. Он вычитает текущее время из времени сервера, чтобы определить дельту времени клиент-сервер, и добавляет половину задержки, чтобы получить правильную дельту часов. (Пока этот algothim очень похож на SNTP)
- Клиент повторяет шаги с 1 по 3 пять или более раз, каждый раз останавливаясь на несколько секунд. В промежуточный период может быть разрешен другой трафик, но его следует минимизировать для достижения наилучших результатов. Результаты приема пакетов накапливаются и сортируются в порядке наименьшей задержки на наибольшую задержку. Медианная задержка определяется путем выбора выборки средней точки из этого упорядоченного списка.
- Все образцы выше приблизительно 1 стандартного отклонения от медианы отбрасываются, а остальные образцы усредняются с использованием среднего арифметического.
Следуя этому примеру, я бы получил это:
Давайте представим, что игра загружена, а время моего клиента равно 0, поэтому я отправляю на сервер, что мое время равно 0.
Сообщение занимает 150 мс, чтобы добраться до сервера, но часы сервера уже запущены и опережают клиента на 1 секунду. Когда сервер получит сообщение, время будет: 1.15 и отправит это время клиенту, хорошо? Давайте представим, что наше отставание постоянно на 150 мс.
Теперь клиент получает время 1,15 и вычитает текущее время из отправленного времени и делит на два, чтобы вычислить задержку. Что составляет: 0,3 - 0 = 0,3 / 2 -> 150 мс.
Он вычитает текущее время из времени сервера, чтобы определить дельту времени клиент-сервер, и добавляет половину задержки, чтобы получить правильную дельту часов:
Время клиента: 0,3 Время сервера 1,15
0,3 - 1,15 = .85 + задержка (.15) = 1
Как это синхронизировано? Что мне не хватает?
Это мой первый опыт многопользовательской игры и работы в сети, поэтому я немного запутался.
Спасибо.
Ответы:
Опубликованный алгоритм был верным, но в своем примере вы забыли о времени, которое требуется для того, чтобы серверный пакет добрался до клиента, поэтому:
Теперь, как вы можете видеть, если бы клиент изменил свои часы на 1.15, он бы отставал от сервера на 0.15, поэтому вам нужно настроить Ping (так называемое Round Trip Time [RTT]). Вот полный расчет времени дельты, сделанный за много шагов:
Это дает нам правильное время дельта 1,00 секунд
источник