Вы, кажется, начали с некоторых хороших идей о синхронизации, но, возможно, есть две проблемы, с которыми вы сталкиваетесь, которые перекрываются: синхронизация игровых часов и синхронизация игрового состояния.
(1) синхронизация игровых часов
вам нужно некоторое представление «игрового времени» для вашей игры. для игры на двоих очень разумно просто объявить одного из них авторитетом.
так на авторитетном клиенте:
OnUpdate()
gameTime = GetClockTime();
msg.gameTime = gameTime
SendGameTimeMessage(msg);
на другом клиенте может выглядеть примерно так:
OnReceivGameTimeeMessage(msg)
lastGameTimeFromNetwork = msg.gameTime;
lastClockTimeOfGameTimeMessage = GetClockTime();
OnUpdate()
gameTime = lastGameTimeFromNetwork + GetClockTime() - lastClockTimeOfGameTimeMessage;
Существуют такие сложности, как пропуск / проскальзывание (то есть получение времени по сети, которое идет вперед / назад слишком много), которые требуют дальнейшей работы, но, надеюсь, вы поняли идею. ответьте на другой вопрос, если вам нужно.
примечание: этот пример не различает «тики» и «секунды», а также не привязан ни к вашему сетевому протоколу, ни к типу устройства, на котором работает ваша игра (сохраните требование «устройство имеет локальные часы») .
(2) синхронизация игрового состояния
После того, как у вас есть согласованные игровые часы, вам все равно нужно будет разобраться, как последовательно имитировать и распространять свое игровое состояние. Для синхронизации игрового состояния у вас есть несколько вариантов:
асинхронный
- каждая единица игрового состояния «принадлежит» одному процессу. только этот процесс может изменить это состояние игры. эти изменения распространяются на все остальные процессы.
- если все принадлежит одному процессу, это часто называют игрой «клиент / сервер».
- примечание: с этой моделью каждый клиент может по-разному смотреть на игровой мир.
- примеры игр: quake, world of warcraft
Чтобы оптимизировать пропускную способность и скрыть задержку, вы можете часто выполнять локальное моделирование для полей с высокой частотой обновления. Пример:
drawPosition = lastSyncPostion + (currentTime - lastSyncTime) * lastSyncVelocity
в этом случае вам, конечно, придется согласовывать новую информацию с вашей имитированной версией.
синхронные
- каждая единица игрового состояния одинакова во всех процессах.
- Команды от каждого процесса передаются друг другу с их желаемым временем инициирования (когда-нибудь в будущем).
- в своей простейшей форме один процесс (часто называемый хостом) отправляет специальные сообщения, указывающие, когда продвигать время игры. когда все получают это сообщение, им разрешено моделировать игру до этого момента.
- требование «в будущем» приводит к большой задержке между входной командой и изменением игрового состояния.
- в играх не в реальном времени, таких как цивилизация, это нормально. в такой игре, как starcraft, обычно звук, подтверждающий ввод, поступает немедленно, но действие, влияющее на состояние игры, задерживается. этот стиль не подходит для таких игр, как стрелялки, требующие чувствительных ко времени действий (в масштабе ~ 100 мс).
синхронно с переимуляцией
- каждая единица игрового состояния одинакова во всех процессах.
- каждый процесс отправляет всем остальным свои входные данные со своей текущей отметкой времени. кроме того, периодически отправляется сообщение «ничего не произошло».
- каждый процесс имеет 2 копии состояния игры.
- копия 1 состояния игры распространяется на «последнее самое раннее сообщение», полученное от всех других клиентов. это эквивалентно синхронной модели, но имеет тот недостаток, что представляет игровое состояние «немного назад»
- копия 2 состояния игры - это копия 1 плюс все оставшиеся сообщения. это прогноз состояния клиента на текущий момент на клиенте, при условии, что ничего нового не произойдет.
- игрок взаимодействует с некоторой комбинацией двух игровых состояний (в идеале 100% копия 2, но необходимо учитывать, чтобы избежать появления всплывающих окон при поступлении новых сообщений)
- примеры игр: уличный боец 4 (интернет игра)
из вашего описания, варианты (1) и (3), кажется, соответствуют вашей проблеме. еще раз, если у вас есть дополнительные вопросы или вам требуется более детальная информация, попросите продолжить.