Как стать автором
Обновить

Оптимизация GameThread в Unreal Engine 4 ч.2

Время на прочтение6 мин
Количество просмотров5.4K

Продолжаем тему оптимизации процессов, с предыдущей частью можно ознакомится по ссылке: Часть 1

Scene Component

После оптимизации анимаций в GameThread, может появится большое количество Scene Component. Они относятся к объектам, которые имеют свою позицию в мире, и их Transform рассчитывается в GameThread. Если есть необходимость обновлять большое количество объектов на большой сцене и на каждом объекте висит множество Scene Component. Объем вычисления становится невероятно большим. Хоть UE и переносит вычисления на асинхронный поток, но все равно ресурсы для обработки процесса требуются немаленькие. С целью оптимизации, в UE были добавлены улучшения для автоматического управления Scene Component, в особенности теми которые закреплены на персонажах и не находятся в активном состоянии.

Включив Auto Manage Attachment для аудио, FX, будет автоматически решатся, висеть ли на родительском Scene Component, в зависимости активен он или нет. В неактивные моменты Transform такого объекта не будет обновлятся.

Каждый раз когда SceneComponent изменяет свое положение в пространстве происходит проверка на Overlap с окружающим миром. При наличии большого количества объектов в каждом кадре будет генерироваться большое количество событий Overlap, что несет за собою потребление существенного количества ресурсов. Основной принцип оптимизации заключается в том, чтобы как можно чаще отключать события, которые не нуждаются в Overlap событии, обратите внимание что по умолчанию этот механизм включен.

Character Movement

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

Spawning

В играх могут спавнится самые разные актеры, но сам процесс очень медленный и потребляет много ресурсов. В первую очередь для оптимизации мы можем использовать как можно меньше ВР компонентов и преобразовывать их в С++. Во-вторых использовать polling метод для систем частиц. И в-третьих применить poolling метод для актеров(при Destroy важных актеров, они не уничтожаются, а заносятся в pool, становясь невидимыми, и в случае необходимости их обратно делают видимым, тем самым нет затраты ресурсов на спавн(например, пули)).

Ticking

Простым языком это обновление логики всех динамических объектов. Возможности движка позволяют выполнять обновление Tick в EventGraph, но это требует расходов ресурсов на вызов BPVM. Одним из методов оптимизации, является перенос логики на С++, другим уменьшение частоты Tick. Для тиков в виджетах применяются Invalidation Panels, для кэширования. В движке есть специальная команда "dumpticks", которая может перечислить все компоненты тиков в текущей сцене. Тем самым можно отследить некоторые вещи, которые должны быть отключены.

Еще одна функция движка TextureStreaming, Эта система вычисляет размеры текстуры, используемой в GameThread, чтобы определить размер необходимых ресурсов для RenderThread и передать их на GPU. Для каждого кадра анализ Mip по-прежнему составляют большую сумму. Когда GameThread требует много ресурсов, то частоту вычисления Texture Streaming можно уменьшить.

UI

Если HUD имеет большое количество объектов UI, расчет их положения будет более сложным и на это уйдет большее количество ресурсов. Для оптимизации вы можете использовать SlatLayoutCaching и Invalidation Box, чтобы уменьшить количество обновлений transform виджетов.

Кроме того, нам также нужно попытаться сделать виджеты UI, пакетными. Некоторые layout в UE, могут вам в этом помочь. Например Horizontal/Vertical Box, Grid и т.д. Они находятся в одном слое и движок будет упаковывать их в первую очередь. При использовании же Canvas Panel, механизм упаковки будет автоматически увеличиваться на единицу за каждый неявный ZOrder. Кроме того для пакетирования, так же важно использование одинаковых материалов и текстур. Потому для инвентаря можно использовать один TextureAtlas, и установить различные Vertex Color для каждой иконки.

LevelStreaming

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

Таким образом, сцена занимает относительно небольшую память и на обработку требуется меньше ресурсов. В то же время, объекты могут быть более сложными при разработки и проектировании. Весь LevelStreaming происходит в три этапа:

  • Input/Output на Working Step

  • Десериализация. После включения Event Driven Loader, IO и десериализация могут быть запущены в разных потоках. Так же десериализацию можно выполнить включив s.AsyncLoadingThreadEnabled и переведя ее в асинхронный ALT.

  • PostLoad. На данном этапе необходимо зарегистрировать объекты в GameThread. В UE это можно сделать асинхронно при помощи TimeSlice. В то же время некоторые PostLoad не влияют на поведение GameThread.

Server Performance

Самый основной метод Replication Graph.

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

C++ UCharacterMovementComponent::GetClientNetSendDeltaTime()
[/Script/Engine.GameNetworkManager]
ClientNetSendMoveDeltaTime=0.05
ClientNetSendMoveDeltaTimeThrottled=0.066
ClientNetSendMoveDeltaTimeStationary=0.0833
ClientNetSendMoveThrottleAtNetSpeed=10000
ClientNetSendMoveThrottleOverPlayerCount=24 

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

На Dedicated server, переключая на OnlyTickMontagesWhenNotRendered, и можно будет заметить что анимации и монтажи не воспроизводятся. Notify, связанные с логикой, montage и AnimSequence, в большинстве случаев не важны для сервера и ими можно пренебречь. Клиент также может иметь похожую логику, но у них есть особые случаи(звуки шагов сделанные игроком не в кадре).

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

Culling

Precomputed visibility Volume позволяют вручную переопределить видимость актеров для их местоположения в мире, если автоматически сгенерированный результат Precomputed Visibility нежелателен. Они также используются для оптимизации производительности и должны быть размещены только в тех областях куда может попасть игрок.

Frustum Culling для оптимизации, все объекты которые не попадают в поле зрения камеры(FOV) скрываются.

Distance Culling убирает из рендера все объекты которые находится слишком далеко от камеры игрока.

Hardware Occlusion метод аппаратного запроса, который выдает GPU проверку видимости каждый кадр в виде запроса для каждого актера. Видимость актера считывается на один кадр позже, тем самым могут быть проблемы в случаях когда камера двигается слишком быстро. Стоимость зависит от количество запросов выполняемых на GPU. Используйте Precomputed и Discance Culling, чтобы уменьшить количество таких запросов.

Software Occlusion метод, который использует назначенные LOD актера, для скрытия тех кто находится за ним. Этот метод растеризирует сцену на CPU для удаление актеров, в то время как HO выполняет проверку на GPU.

Profiling

Что касаемо профилирования, UE имеет большое количество встроенных инструментов, таких как часто используемые команды серии stat и команды серии ShowFlag, которые могут быстро помочь найти проблемы, профилирование cpu, и UE поставляются с собственным инструментом.

Заключение

В Unreal Engine есть безумное количество самых различных методов и решений, которые можно применять для той или иной оптимизации процесса. Подробнее с ними всегда можно ознакомится в официальной документации или на бесконечном количество доступных видео. Скриншоты взяты из: Видео 1 и Видео 2.

Я весьма надеюсь что для вас две статьи были весьма познавательными и интересными, и вы хотя бы что-то узнали новенького.

А на этом я с вами прощаюсь. Всем спасибо за внимание и да прибудет с вами сила знаний.

Теги:
Хабы:
Всего голосов 2: ↑2 и ↓0+2
Комментарии0

Публикации

Истории

Работа

Ближайшие события