Вы задали этот вопрос 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 мс в будущем.