Отправка различий состояния (дельты) и ненадежных соединений

8

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

Обновления состояния передаются с использованием ненадежного UDP .

Чтобы минимизировать отправку данных о состоянии, мы создали систему, которая будет отправлять только дельты (независимо от того, какие данные о состоянии были изменены).

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

Например:

Предположим, что состояние состоит из: {positionX, positionY, health}

Frame 1  - positionX changed --> send a packet with positionX only.
Frame 2 - health changed // lost !
Frame 3 - positionY changed --> send a packet with positionY only.

// Другие игроки не знают об изменении здоровья.

Как можно решить эту проблему? отправка всей информации не всегда возможна.

spaceOwl
источник

Ответы:

7

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

Evan
источник
2
Ударь меня к этому. Однако следует отметить, что довольно изменчивые значения, такие как положение и другие физические данные, не должны быть гарантированы. Даже если нет вероятности, что это неправильно в данном кадре, он все равно будет исправлен в следующем кадре.
jmegaffin
1
Хорошая мысль, это чаще всего наблюдается в играх, когда персонаж внезапно очень быстро перемещается в новое место (или телепортируется туда все вместе). Большинство игр справляются с этим несколькими различными способами, но цель одна и та же. Сервер просто обновил положение объекта, и ваш клиент либо немедленно обновит, либо обновит его с очень большим временем разности в течение нескольких кадров.
Эван
3

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

Матиас
источник
3

Многие игры используют как UDP, так и TCP / IP для отправки / получения данных, и в зависимости от того, как часто данные отправляются, используется другой протокол.

Например:

UDP: позиционные обновления и все остальное, что потенциально может быть отправлено / получено несколько раз в секунду.

TCP / IP: действия инвентаря, действия заклинания / способности, (большинство действий, выполненных пользователем)

Это действительно зависит от количества трафика каждого элемента. Если вы обнаружите, что отправляете обновления HP довольно часто, возможно, они должны быть по UDP.

UnderscoreZero
источник
1
TCP, как правило, не используется для чего-либо, что требует точности в реальном времени, потому что его способность вызывать большие скачки задержки.
TheNickmaster21
Хорошо, если вы хотите убедиться, что ваш пакет туда попал. Такие вещи, как позиционные обновления, не годятся для этого, но если вы хотите убедиться, что ваш пользователь нажал кнопку в определенное время, TCP обрабатывает все проверки ошибок и другие вещи, которые вам придется реализовать для UDP, чтобы избежать потери пакетов.
UnderscoreZero
Действительная точка; Я бы предпочел изменить UDP.
TheNickmaster21
1

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

По сути, в вашей модели вы отправляете дельты против непосредственно предыдущего состояния. В модели quake3 вы отправляете дельты относительно последнего подтвержденного состояния от партнера.

minism
источник