Задать вопрос
@ASMcoder-Source

Можно ли использовать TCP протокол для игрового сервера?

Написал простой сервер на TCP сокетах, используя WinAPI. Сейчас код представляет из себя просто синхронизацию, в стиле: клиенты отправляю пакет с данными своего персонажа, он рассылается всем остальным, и клиенты обновляют позицию этого игрока у себя.

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

Из этого возникает вопрос, это недостаток TCP такой, или вероятнее кривость кода? ( У меня есть предположение что используя TCP, идёт какая-то проверка на принятие пакета, а это уже значит ожидание ответа, а это уже 20-300 миллисекунд может быть. И так на каждом клиенте в списке для рассылки. )
  • Вопрос задан
  • 182 просмотра
Подписаться 1 Простой 1 комментарий
Решения вопроса 3
@rPman
Во первых, собирай статистику по фреймам, смотри на графиках, почти наверняка это будут периодические пики с превышением времени на доставку данных

Между фреймами не должна стоять фиксированная пауза, правильный подход - засекаешь время, отправляешь запрос по сети, обрабатываешь его и затем вычисляешь, сколько времени осталось ждать

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

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

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

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

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

Но главное, сетевой трафик в такой схеме значительно снижается, ведь рассылаются буквально только нажимаемые клавиши и изредка хеш-суммы состояния мира для валидации их корректности (все клиенты и сервер по завершению каждого фрейма должны сравнить состояния друг друга например путем вычисления хеш суммы по отсортированным объектам, всем или по какому то критерию, например попадающим в ячейку матрицы по координатам, если там происходили изменения)
Ответ написан
Комментировать
AgentSmith
@AgentSmith
Это мой правильный ответ на твой вопрос
Можно ли использовать TCP протокол для игрового сервера?

Да, можно.
Насчёт скорости - она зависит от того как идёт маршрутизация до клиента и обратно
Ответ написан
Комментировать
MvcBox
@MvcBox
Software Engineer [C/C++/JS(for Node.js)/etc]
Но столкнулся с такой проблемой, даже с учетом того что сервер выполняет это действие каждые 8мс, в самой игре, перемещение получается слишком рывковое

https://en.wikipedia.org/wiki/Client-side_prediction
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
saboteur_kiev
@saboteur_kiev Куратор тега Разработка игр
software engineer
200 ms это много.
Считается, что 20-40 мс достаточно для шутеров. Меньше - достаточно для про-чемпионата в локалке.
При этом 20-40 мс это при отправке килобайтного пакета.
Вопрос в том, что вы отправляете, как часто и как много клиентов.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы