Я заинтересован в оценке различных способов, которыми сетевой код может «зацепиться» за игровой движок. Сейчас я разрабатываю многопользовательскую игру, и пока я решил, что мне нужно (как минимум) иметь отдельный поток для обработки сетевых сокетов, отличный от остальной части движка, который обрабатывает графический цикл и скрипты.
У меня действительно был один потенциальный способ сделать сетевую игру полностью однопоточной, а именно проверять сеть после рендеринга каждого кадра, используя неблокирующие сокеты. Однако это явно не оптимально, потому что время, необходимое для рендеринга кадра, добавляется к задержке сети: сообщения, поступающие по сети, должны ждать, пока не закончится рендеринг текущего кадра (и логика игры). Но, по крайней мере, таким образом, игровой процесс будет оставаться более или менее плавным.
Наличие отдельного потока для работы в сети позволяет игре полностью реагировать на работу в сети, например, она может отправлять обратно пакет ACK сразу после получения обновления состояния от сервера. Но я немного озадачен тем, как лучше общаться между кодом игры и кодом сети. Сетевой поток будет помещать полученный пакет в очередь, а игровой поток будет читать из очереди в соответствующее время в течение своего цикла, поэтому мы не избавились от этой задержки до одного кадра.
Кроме того, кажется, что я хотел бы, чтобы поток, который обрабатывает отправку пакетов, был отделен от того, который проверяет пакеты, поступающие по каналу, потому что он не сможет отправить один из них, пока он находится в середине проверка, есть ли входящие сообщения. Я думаю о функциональностиselect
или подобном.
Я предполагаю, что мой вопрос, каков наилучший способ создать игру для лучшей скорости отклика сети? Ясно, что клиент должен посылать пользовательский ввод как можно скорее на сервер, чтобы я мог сделать так, чтобы код net-send приходил сразу после цикла обработки событий, как внутри цикла игры. Есть ли в этом смысл?
источник
Нет, ты не
Не обязательно имеет значение. Когда обновляется ваша логика? Нет смысла выводить данные из сети, если вы пока ничего с этим не можете сделать. Точно так же нет смысла отвечать, если вам пока нечего сказать.
Если ваша игра так быстро развивается, что ожидание рендеринга следующего кадра является значительной задержкой, то она будет отправлять достаточно данных, чтобы вам не нужно было отправлять отдельные пакеты ACK - просто включите значения ACK в ваши обычные данные полезные нагрузки, если они вам нужны вообще.
Для большинства сетевых игр вполне возможно иметь такой игровой цикл:
Вы можете отделить обновления от рендеринга, что настоятельно рекомендуется, но все остальное в значительной степени может оставаться таким простым, если у вас нет особых потребностей. Какую игру вы делаете?
источник
Это совсем не так. Сообщение передается по сети, пока получатель воспроизводит текущий кадр. Сетевая задержка ограничена целым числом кадров на стороне клиента; да, но если у клиента так мало FPS, что это большая проблема, тогда у него большие проблемы.
источник
Сетевые коммуникации должны быть пакетными. Вы должны стремиться к тому, чтобы один пакет отправлял каждый тик игры (что часто происходит при рендеринге фрейма, но действительно должно быть независимым).
Ваши игровые сущности общаются с сетевой подсистемой (NSS). NSS объединяет сообщения, ACK и т. Д. И отправляет несколько (возможно, один) UDP-пакетов оптимального размера (обычно ~ 1500 байт). NSS эмулирует пакеты, каналы, приоритеты, повторную отправку и т. Д., Отправляя только отдельные пакеты UDP.
Прочитайте учебник по играм или просто используйте ENet, который реализует многие идеи Гленна Фидлера.
Или вы можете просто использовать TCP, если ваша игра не нуждается в подергиваниях. Тогда все проблемы с пакетированием, повторной отправкой и ACK исчезают. Однако вы все равно хотели бы, чтобы NSS управлял пропускной способностью и каналами.
источник
Не полностью «игнорировать отзывчивость». Добавление дополнительной задержки в 40 мс к уже задержанным пакетам мало что дает. Если вы добавляете пару кадров (со скоростью 60 кадров в секунду), то вы задерживаете обработку позиции, обновляя еще пару кадров. Лучше быстро принимать пакеты и обрабатывать их, чтобы повысить точность моделирования.
Я добился большого успеха в оптимизации пропускной способности, подумав о минимальной информации о состоянии, необходимой для представления того, что видно на экране. Затем посмотрите на каждый бит данных и выберите модель для него. Информация о местоположении может быть выражена в виде дельта-значений во времени. Вы можете использовать для этого свои собственные статистические модели и целую вечность отлаживать их, или вы можете использовать библиотеку, чтобы помочь вам. Я предпочитаю использовать модель с плавающей точкой этой библиотеки DataBlock_Predict_Float. Это позволяет очень легко оптимизировать полосу пропускания, используемую для графа игровой сцены.
источник