ИСТРЕБИТЕЛИ БАГОВ: БЕЗУМИЕ ЧАСТОТЫ ОПРОСА

На Star-Citizen.ru выложили перевод очередного выпуска Истребители багов. Весьма примечательный выпуск показывающий то как на самом деле сложно всё устроено.

Марк Эйбент не ожидает, что эти баги заговорят. Он ожидает, что они умрут. Так и будет, ведь на этой неделе наш местный мастер-истребитель берется устранить клиент-серверную ошибку, которая вызывает проблемы при взлете.

Всем привет. Мы находимся на карте Постоянной Вселенной. Знаю, вам нравится мой забавный тестовый уровень, но, к сожалению, для воспроизведения этого бага он не подойдет. Я нахожусь в своем Gladius, и у нас тут такой веселый баг: когда показатели FPS на клиенте и на сервере начинают слишком сильно различаться (на сервере слишком низкий, тогда как на клиенте слишком высокий – из-за большого количества вносимых нами оптимизаций), существует шанс, что при попытке взлететь вы сначала немного подергаетесь на месте, а затем уже оторветесь от земли. Посмотрим, удастся ли нам повторить эту ошибку, и для этого прикажем серверу принудительно работать с частотой 5 FPS. Да, вот так, потому что я монстр. Итак, серверы работают при 5 FPS, тогда как у меня на клиенте порядка 30 FPS.  Теперь я попытаюсь воспроизвести баг и для этого подготовлю корабль к полету. Теперь я получил контроль над кораблем и пробую взлететь. Как видите, я действительно не могу оторваться от земли – корабль дергает и трясет.

Поставим в коде точку остановки. В общем, это код полетного контроллера IFCS или сетевой системы корабля. Класс ServerPlayer здесь – это, по сути, серверное представление корабля. У меня также есть клиентская версия этого класса, и они делятся друг с другом информацией – поэтому сервер знает, что пытается сделать клиент, и наоборот. В данной ситуации у нас получается, что сервер пытается обработать какие-то пакеты, поступающие от клиента, но не может этого сделать, потому что частота опроса у клиента составляет 4000 тактов, а последнее полученное им от сервера значение частоты опроса превышает 5000 тактов. Из-за этого сервер никогда не обрабатывает состояние клиента. Довольно необычно.

Вот что происходит в действительности. Когда я впервые сажусь в корабль, сервер контролирует практически всю систему. А когда я провожу предполетную подготовку, я говорю серверу, что готов взять управление этим кораблем на себя. Теперь я локальный клиент, и я должен указывать серверу, что я собираюсь делать с кораблем: двигаться влево, вправо, вперед, назад и т.д. В этот момент клиент как бы обладает полномочиями для управления кораблем, но сервер может вмешаться и сказать: «мне не нравится то, что ты делаешь», и скорректировать текущее состояние корабля по своему усмотрению. В этот момент сервер пытается перехватить контроль у клиента, однако из-за низкого показателя FPS он выполняет обновления медленнее клиента. Получается, что когда мы передаем полномочия серверу, клиент корректирует свое положение согласно данным с сервера, и это задает ему частоту опроса в 4000 тактов. Однако же время, когда сервер последний раз получал обновления от клиента, составляет 5000 тактов. В общем, мы попадаем в такую странную ситуацию, что при передаче полномочий и захвате частоты обновлений сервер… портится. Причина кроется в том, что мы привязались к состоянию клиента, но последний раз сервер слышал о клиенте еще когда тот обладал возможностью управлять кораблем. В конечном счете частота опроса клиента должна подняться до 5000 перед тем, как я смогу взлететь. Это большая проблема, потому что я не могу ждать целый день. На самом деле, если вы сядете в кабину, просидите там 10 минут, а затем решите взлететь, вам придется прождать еще 10 минут прежде чем вы действительно сможете оторваться от земли. Не очень весело.

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

Нам нужно убедиться, что клиент реагирует на обрыв управления и передачу полномочий серверу для совершения коррекции. Мы спросим клиента, какой по его мнению должна быть частота опроса. Итак, когда сервер захочет совершить коррекцию, он изменит значение булевой переменной на «true», и это будет означать, что мы ждем, пока клиент повторно обработает полученные данные. Вдобавок мы избавимся от странного решения, когда мы отправляем -1 в качестве текущей частоты опроса.  -1 тут значит, что мы не хотим совершать коррекцию. Любое другое значение, напротив, будет означать, что мы хотим ее совершить. Перепишем эту часть. Вместо -1 нам нужно отправлять клиенту время совершения сервером последней коррекции. И если текущая частота опроса не согласуется с полученным значением, значит мы привязываемся к той частоте, которую выдал нам сервер. Так клиент будет знать, что необходимо передать полномочия серверу для коррекции положения корабля.

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

Мы определили процесс совершения коррекции и теперь будем постоянно получать от сервера актуальные значения частоты опроса. Сама коррекция, в общем случае, телепортирует нас туда, куда укажет сервер: клиент получает от сервера данные о новом положении и перескакивает туда. Теперь черед за сервером.  Клиент ответил: «я совершил коррекцию в этот момент времени». Если проведенная им коррекция согласуется с ожиданиями сервера, и сервер в данный момент ждет ответа о проведении коррекции, мы обработаем результат и продолжим дальше.

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

Мы вернулись в корабль. Давайте попробуем взлететь. Успех, мы можем взлететь! Интерфейс немного дрожит, но я тем не менее могу оторваться от земли и полететь. Похоже, мы устранили проблему. Когда мы заставляем игру работать быстрее, мы сталкиваемся вот с такими вот забавными проблемами. Надеюсь, вам понравились эти сетевые уловки, и увидимся в следующий раз.

Как вы могли видеть, у нас был небольшой забавный баг, который возникал из-за значительных расхождений в частоте кадров на клиенте и сервере. Такого не должно было происходить, но при определенных условиях это все же случалось. С того момента, как мы существенно повысили FPS на клиенте, его частота обновления начала слишком сильно расходиться с частотой обновления на сервере. Из-за этого возникали различные проблемы с сетевой частью IFCS. Теперь мы все исправили, и всякий раз, когда серверу понадобится скорректировать положение клиента, он без проблем сможет это сделать.

ПОХОЖИЕ СТАТЬИ

КОРАБЕЛЬНАЯ ВЕРФЬ: ТОПЛИВНЫЕ МЕХАНИКИ

КОРАБЕЛЬНАЯ ВЕРФЬ: ТОПЛИВНЫЕ МЕХАНИКИ

Как они работают сегодня, и что припасено на будущее С релизом серии 100 от Origin с ее уникальной системой AIR мы хотели бы потратить немного времени и поговорить о текущей и будущей роли топлива в Star Citizen. Профессия заправщика (а заодно и связанный с топливом геймплей) являются...

СЕРИЯ ORIGIN 100: ВОПРОСЫ И ОТВЕТЫ, ЧАСТЬ 1

СЕРИЯ ORIGIN 100: ВОПРОСЫ И ОТВЕТЫ, ЧАСТЬ 1

Привет всем. Вслед за запуском серии Origin 100 ниже мы приводим ответы на некоторые вопросы, чтобы предоставить вам больше информации об этих совершенно новых стартовых кораблях от Origin Jumpworks. У вас еще остались вопросы, на которые мы не ответили ниже? Публикуйте их в...

ПРЕДСТАВЛЯЕМ 100-Ю СЕРИЮ ОТ ORIGIN

ПРЕДСТАВЛЯЕМ 100-Ю СЕРИЮ ОТ ORIGIN

Заявите о себе ГАРМОНИЯ МЕЖДУ ПИЛОТОМ, МАШИНОЙ И ОКРУЖЕНИЕМ Origin с гордостью представляет эволюцию приключения – 100-ю серию. Весь тот класс и изысканность, которые у вас уже ассоциируются с Origin Jumpworks, элегантно представлены в привлекательном компактном кузове. 100-я серия была...

Оставить комментарий