Истребители багов: постоянное обновление кораблей

Истребители багов: постоянное обновление кораблей

Истребители багов: постоянное обновление кораблей

Выпуск от 8 ноября 2017г.

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

На тестовой сцене загружен уровень PU и Cutlass. Марк создает еще несколько копий корабля, которые появляются в одной точке и вызывают сильный клиппинг. Выглядит довольно забавно. Теперь у нас есть Port Olisar, рядом с которым летает горстка кораблей.

Суть проблемы становится понятна, когда Марк при помощи консольной команды перемещает игрока на орбиту Yela, а созданные Cutlass после этого все равно продолжают обновляться, вызывая падение производительности. Эту проблему необходимо устранить, если мы хотим получить поддержку большого числа игроков на сервере. Мы не должны обновлять параметры сущностей для другого игрока, который находится где-то очень далеко от них. Фактически, для игрока совершенно не важно, что где-то в галактике M50 сражается с Cutlass. С его точки зрения они лишь съедают циклы процессора.

Первое, на что Марк обратил внимание, это код компонента для перемещения в полете. Он очень простой. Все что он делает – это инициализируется, получает информацию о транспортном средстве и начинает обновлять IFCS на этапе группового обновления. На определенном кадре обновления сущностей мы, по сути, формируем группу обновлений, после чего они появляются и начинают обрабатываться всеми доступными процессорами. В общем, во время просчета кадра система посылает запрос на обновление всех сущностей, и мы просто сходим с ума от их количества. Преимущество такого подхода в том, что вместо одного прохода и обработки только одной сущности в каждый момент времени, мы можем запустить 16-20 тысяч обновлений подряд, что довольно эффективно. Однако у функции задан параметр "всегда обновлять", который указывает, что даже если объект находится очень далеко, он все равно будет обновляться.

В коде существует целая уйма обновлений, но на данный момент нас беспокоит лишь одно из них – то, что называется "в радиусе". Какая-то сущность в радиусе не обязательно является невидимой, но если она потенциально видима, то она может находиться за игроком, слева или справа от игрока – где угодно, и при этом она будет получать обновления. То есть если я с кем-то сражаюсь, и противник заходит с тыла, так что я перестаю его видеть, его сущность продолжает обновляться для меня, потому что нам нужно, чтобы его корабль продолжал лететь. Мы внесли исправление, но оно вызвало некоторые проблемы, особенно с работой IFCS, поскольку мы исполняем некоторые сетевые технологии, которые больше не встречаются. Поэтому нам нужно скопировать несколько функций. Мы хотим сообщить IFCS, что при выходе из заданного радиуса нужно остановить движение и обработку физики, а при заходе в радиус – перезагрузить сетевую технологию, чтобы захватить самую свежую информацию о положении корабля.

Марк добавляет две функции, которые позволяют компоненту регистрировать определенные события. При получении события становится возможным выполнить какое-то действие. Теперь нужна сама регистрация событий. Из всего множества событий в коде нам нужно всего два: "вход в радиус" и "в радиусе". Самая интересная особенность работы событий "в радиусе" и "покидание радиуса" в том, что радиус на клиенте – это, фактически то место, где находится игрок. То есть мне как игроку нет дела до M50 где-то вдалеке. Но радиус на сервере – это место, где находятся все игроки. Получается, что технически если два игрока находятся в разных концах галактики, то объекты в зонах вокруг них будут обновляться на сервере. При этом на моем клиенте будут обновляться только те объекты ,которые находятся внутри зоны вокруг моего персонажа. Толковая вещь, которая заставляет игровой код работать, особенно для важных нам игровых объектов. Все сущности, которые находятся за пределами радиуса и которые не нужно обновлять, не должны обновляться. Вернем обратно наши циклы ЦП.

После регистрации и обработки событий "в радиусе" и "за пределами радиуса" добавляем транспортное средство и даем ему понять, когда мы входим в радиус. Это будет новая функция типа Boolean по имени OnRangeChange ("при изменении радиуса"). При входе сущности в радиус функция будет принимать значение True, а при выходе из радиуса – False. Теперь обработка должна начинаться, если объект находится в радиусе.

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

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

Как только мы отправились в сон, если корабль попадет в радиус, нужно будет его разбудить. Для сервера это перезагрузит сеть. Также нужно будет сбросить наши предсказания. Как же это работает? Если сервер попадает в такое состояние, где корабль возвращается обратно в наше поле видимости, он перезагружает состояние сети, и все обрывается. Затем на стороне клиента мы задаем предсказание, и оно фиксирует самую свежую информацию клиента или сервера.

Компилируем проект, наблюдаем чудесные ошибки и затем возвращаемся на тестовый уровень в окрестностях Port Olisar. Снова создаем несколько Cutlass. Они обновляются, IFCS делает свою работу для стабилизации их положения. После телепортации к Yela мы не наблюдаем текста отладки на экране, а это значит, что корабли перестали обновляться. Мы вернули обратно свои циклы ЦП, все счастливы, FPS высокий! Но что особенно замечательно – сервер не будет обновлять эти сущности, пока игрок не окажется поблизости. Но, конечно, если бы здесь был другой клиент, то сервер продолжил бы обновлять эти корабли, поскольку нужно было бы рассчитывать их перемещения.

Вот такая сегодня получилась веселая оптимизация. В попытках наполнить сервер все большим числом игроков разработчики постоянно выполняют отладку, профилирование и пытаются выяснить, какие вещи в процессе просчета отнимают большую часть времени на сервере. Затем их отлавливают, чтобы получить возможность добавить больше игроков. К сожалению, корабли присутствовали в игре уже очень давно (ведь это игра про космос), и разработчики старались побыстрее заставить их работать. Вот почему у судов не было достаточного числа оптимизаций. Но когда вы начинаете добавлять больше игроков, не нужно выполнять все эти обновления. Не нужно обновлять IFCS для тех ребят, которые находятся чёрт знает где. Марк внес некоторые изменения в код, чтобы для вашего клиента удаленные игроки отправлялись в некое подобие режима гибернации до тех пор, пока они не приблизятся к вам.

Перевод: H_Rush

Обсудить на форуме star-citizen.ru

H_Rush administrator