Сетевая задержка в многопользовательской мобильной игре - PullRequest
1 голос
/ 05 марта 2012

Мы используем Corona SDK и его физический движок для перемещения объектов по некоторому ландшафту (например, Tiny Wings), и у нас есть вопрос относительно коррекции позиций. Скажем, коробка движется по холмистой местности, но ее положение вычисляется на другом устройстве. Несколько раз в секунду вы получаете:

  • обновленная позиция
  • скорость коробки
  • время отправки информации

Итак, мы знаем, что информация устарела на X миллисекунд, и хотели бы выяснить, где она должна быть к настоящему моменту (при условии, что она зависит от физики), и продолжать моделирование, пока мы не получим очередное обновление. Прямо сейчас мы попытались просто умножить скорость на количество времени с момента отправки посылки, но, как вы можете себе представить, это ведет себя очень плохо, если местность изогнута / не плоская.

Есть ли способ сказать: «Остановите все и дайте мне позицию, которую занимало бы это окно, если бы физика воздействовала на него в течение X мс, затем возобновите игровой процесс», фактически не останавливая весь игровой процесс в течение X мс?

Ответы [ 2 ]

0 голосов
/ 30 ноября 2013

Вы задали этот вопрос 20 месяцев назад, возможно, вы уже решили это, но я просто постараюсь ответить на него для будущих посетителей:

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

В принципе нет никакой разницы между сетевой физикой и сетевой игровой логикой, это одновременно и сетевая синхронизация . Мы можем попытаться абстрагировать его, чтобы обозначить, что есть какое-то событие (пространство + время + состояние) , с которым должны согласиться все участники. Это событие может быть определенным состоянием объекта, рассчитанным физическим движком или чем-то еще.

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

Существует способ сделать синхронизацию, которая работает лучше (на мой взгляд): узел не должен сообщать, каково его текущее состояние, а вместо этого сообщать, в каком состоянии он хочет, чтобы объект имел X миллисекунд в будущем * 1018. *.

Двигатель должен попытаться сделать Х как можно ближе к сумме:

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

Примечание: он может найти наблюдаемую задержку , непрерывно отправляя сообщения и анализируя время отклика

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

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

Поворот симуляции, в который попадает X-я миллисекунда, можно назвать поворотом цели.

(будущие читатели: обратите внимание, что повороты симуляции часто не идентичны FPS, часто они встречаются гораздо реже, например, каждые 10 кадров или каждые 100 мс или , и мне нравится это лучше всего так же быстро, как и сеть может доставить)

* +1054 * Пример:
[Turn0] a client/physicsengine announces event e1
[Turn1] a client/physicsengine announces event e2
[Turn2] (other stuff)
[Turn3] (other stuff)
[Turn4] (other stuff)
[Turn5] clients start interpolating towards e1
[Turn6] clients start interpolating towards e2
[Turn7] e1 target-turn: e1 should be true/fulfilled now
[Turn8] e2 target-turn: e2 should be true/fulfilled now
[Turn9] 

Что делать, если два клиента не согласны с тем, что будет определенным событием? Прежде всего обратите внимание, что это может быть обнаружено каждым клиентом независимо, потому что у каждого есть временная шкала, где повороты становятся согласованными до того, как они достигают . Что делать, зависит от вашего приложения и от того, какое это событие:

  • Есть много событий, у которых нет игрового эффекта , например. если ваш физический движок рассчитал что-то только для более приятной графики. Эти события могут быть просто забыты.
  • Для других событий не будет иметь значения, если одна или другая версия будет выполнена, если оба клиента согласны. Клиенты могут выбирать версию децентрализованно (без необходимости общения), основываясь на некоторой эвристике.
  • В других случаях может случиться, что событие A аннулирует событие B, а B аннулирует A: в этом случае вы можете позволить серверу принять решение и повторно запланировать еще одну X мс в будущем.
0 голосов
/ 22 марта 2012

Я не знаю о Corona SDK, но один из способов, которым вы можете это сделать, - это симулировать ваш физический мир на протяжении всего игрового цикла в каждом игровом цикле. И когда вы получите реальную позицию, вы можете обновить свой физический мир.

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

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

...