Как компенсировать движущиеся объекты с помощью предсказания на стороне клиента?

11

Я реализую игровой сервер, который поддерживает Star Control-подобный рукопашный бой . Таким образом, у вас есть корабли, летающие и стреляющие, с супер простой физикой скорости / ускорения / демпфирования для управления движением.

введите описание изображения здесь

Я прочитал Valve, Gafferon и Gambetta и реализовал алгоритм Gambetta для предсказания клиента:

введите описание изображения здесь

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

К сожалению, это плохо работает для моей игры. Я полагаю, что это связано с тем, что пример Гамбетты не учитывает объекты, которые уже перемещаются, или команды, которые обновляются шаг за шагом. (под «шагом» я подразумеваю кадр). Поэтому в моей игре игрок нажимает, чтобы ускорить (уже движущийся) корабль, который продолжает двигаться на клиенте, отправляет команду на сервер и обычно получает снимок мира с сервера на следующем шаге. Я получаю что-то более похожее на:

введите описание изображения здесь

Команда проигрывателя выполняется на шаге 3 клиента , но на сервере она запускается только на шаге 5 сервера . К тому моменту, когда на шаге 6 клиента будет получен моментальный снимок мира , предсказание уже далеко, особенно при более высоких скоростях.

Суть проблемы в том, что клиент запускает команду на шаге 5 , а сервер запускает ее на шаге 6 . Я подумал о том, чтобы отправить клиентский шаг с помощью команды, чтобы сервер откатился и повторно запустил команду с временным шагом клиента. Это может привести к множеству других проблем - например, что происходит с командами, полученными после отката, или как обманывать клиентов можно, изменяя отправленный шаг.

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

Мои вопросы:

  • Можете ли вы заставить алгоритм Гамбетты работать с постоянным шаговым движением? Или это концептуально несовместимо с моей игрой?

  • Является ли постепенная интерполяция по шагам правильным путем? Если да, как вы интерполируете уже движущийся объект с позиции клиента, чтобы соответствовать тому, что только что было получено с сервера?

  • Могут ли эти методы, постепенная интерполяция и алгоритм Гамбетты работать в тандеме или они взаимоисключающие?

OpherV
источник
Я делал то же самое и столкнулся с точно такой же проблемой. Как только я добавил скорости, применяя состояние сервера и повторно применяя входы, я избавился от уже обработанных изменений скорости. Я пытался повторно применить все обновления с момента последнего полученного сообщения, но это пока не очень гладко. Вы когда-нибудь находили решение для этого?
MakuraYami
@MakuraYami Да - я начал писать статью с описанием решения. Скоро обновлю!
OpherV
Я больше работал над своим проектом и нашел полезное решение и еще несколько хороших ресурсов, рассказывающих об этой проблеме. Мне интересно обсудить дальше, сравнить решения и т. Д. Дайте мне знать, где я могу с вами связаться :)
MakuraYami
@makurayami мое имя пользователя в Gmail
OpherV

Ответы:

5

В течение 6 месяцев после того, как я задал этот вопрос, я закончил разработку полного игрового сервера с открытым исходным кодом для решения именно этой проблемы (и многих других!): Http://lance.gg

введите описание изображения здесь

Исследования и разработки теперь позволяют мне отвечать на мои собственные вопросы:

  • Можете ли вы заставить алгоритм Гамбетты работать с постоянным шаговым движением? Или это концептуально несовместимо с моей игрой?

    Алгоритм Гамбетты не будет работать, когда движение объекта не является детерминированным (из POV клиента). Если сущность может быть затронута без участия физики или других игроков, например, необходимо использовать более гибкий подход.

  • Является ли постепенная интерполяция по шагам правильным путем? Если да, как вы интерполируете уже движущийся объект с позиции клиента, чтобы соответствовать тому, что только что было получено с сервера?

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

  • Могут ли эти методы, постепенная интерполяция и алгоритм Гамбетты работать в тандеме или они взаимоисключающие?

    Они могут работать вместе, но только если движение объекта детерминировано из POV клиента. Так что это не будет работать, если на сущность влияют физика или псевдо-физика, такие как вставка, перетаскивание и т. Д. '

OpherV
источник
1

Кажется, ваша игра слишком "в реальном времени", чтобы думать с точки зрения временных шагов. Я бы подумал только о «поворотах», если бы игру можно было считать «пошаговой». В противном случае, просто отказаться от идеи поворотов или шагов. Тогда все становится проще :)

Обратите внимание, что вы прогнозируете локально для своего игрока и интерполируете только для других объектов (как объяснено в 3-ей статье в серии). Способ работы с серверными обновлениями для объектов, которые уже перемещались, - это согласование на стороне сервера, объясненное в нижней половине 2-й статьи (на которую вы ссылались).

Надеюсь это поможет :)

ggambett
источник
Просто чтобы уточнить - под «шагом» я подразумеваю «кадр», который запускается 60 раз в секунду. Я называю это шагом (а не фреймом), чтобы отличить реальное развитие игры от рендеринга, и в идеале они оба синхронизируются со скоростью 60 в секунду. Я уже реализовал вашу версию согласования на стороне сервера, которая прекрасно работает. Этот вопрос касается только корабля игрока - который постоянно движется независимо от команды игрока (из-за инерции). Вот где моя трудность. Есть мысли по этому поводу? :)
OpherV
Рамки отличаются от шагов. Шаги движутся в постоянном, предсказуемом порядке. Кадры перемещаются разное количество времени, поэтому любая последовательность должна быть умножена на время дельты для этого кадра.
Tealr
@Tealr действительно, именно поэтому я использовал термин «шаг» для начала - я просто хотел прояснить, что использование «шага» не ограничивается пошаговыми играми, и в моей игре шаг занимает ровно 1 / 60 секунд независимо от рендеринга.
OpherV
Просто кое-что, что я отмечаю для моих собственных экспериментов: 1/60. Это необычайно быстро, и я держу пари, что большинство онлайн-игр с участием более 1х1 работают в 1/10. обновления или около того.
Патрик Хьюз