Всё больше проектов появляется на Unreal Engine — от великого "Ведьмака" до не менее великой "The Day Before". И чем больше проект, тем выше цена одной незамеченной ошибки. Когда число строк кода переваливает за несколько тысяч, даже самый внимательный разработчик может не заметить неочевидный баг. И тут на помощь приходит он — PVS-Studio, который помогает снизить риск попадания багов в ваши UE-проекты.

Введение

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

У статического анализатора PVS-Studio богатый опыт сотрудничества с Epic Games и Unreal Engine. И с каждым релизом в PVS-Studio появляется всё больше механизмов и специализированных для Unreal Engine диагностических правил. Давайте же посмотрим, к каким результатам привели годы развития интеграции PVS-Studio с одним из самых популярных игровых движков.

Примечание. Подробнее о необходимости статического анализа в GameDev мы рассказывали в статье ранее на примере движка Unity.

Установка PVS-Studio и плагинов

Подключить PVS-Studio к Unreal Engine несложно. Скачиваем инсталлятор по ссылке и следуем инструкции — устанавливаем сам PVS-Studio и плагин для Visual Studio 2022. Понадобится Enterprise-лицензия, если её нет, можно получить триальную по этой ссылке.

Быстрый старт на Windows описан в документации.

Способы запуска анализа

Попытка проанализировать проект на Unreal Engine привычным способом — через плагин в Visual Studio — приведёт к сообщению о невозможности запуска анализа. Unreal Engine использует собственную систему сборки UnrealBuildTool (UBT), и именно через неё должен запускаться анализ. Поэтому давайте рассмотрим первый способ запуска анализа — через флаги UBT.

Флаги UnrealBuildTool

Как я уже ранее упоминал, Unreal Engine компилирует проекты через UBT. Чтобы проанализировать проект, нужно добавить в UBT следующий флаг:

-StaticAnalyzer=PVSStudio

Этот флаг нужно прописать в поле NMake Command Line в настройках проекта. В этом случае вместо сборки проекта будет производиться анализ. При первом запуске будет произведён полный анализ проекта, при последующих — только изменённых файлов (инкрементальный анализ). Если указать флаг в команде Rebuild, анализ будет запускаться каждый раз для всего проекта.

Подробности о сценариях запуска сборки и анализа можно найти в документации.

Задание параметров в .target.cs файлах

Если вы часто пересоздаёте .sln или регулярно пересобираете проект, удобнее всего зашить параметры анализа прямо в .target.cs.

Для этого просто добавьте одну строку в конструктор Target, в зависимости от версии Unreal Engine.

Unreal Engine 5.0 и ниже:
public MyProjectTarget(TargetInfo Target) : base(Target)
{
    ....
    WindowsPlatform.StaticAnalyzer = WindowsStaticAnalyzer.PVSStudio;
    ....
}
Unreal Engine 5.1 и выше:
public MyProjectTarget(TargetInfo Target) : base(Target)
{
    ....
    StaticAnalyzer = StaticAnalyzer.PVSStudio;
    ....
}

Через файл BuildConfiguration.xml

Если нет возможности менять .target.cs файлы, то можно задать параметры анализа через отдельный конфигурационный файл — BuildConfiguration.xml.

Пример минимальной конфигурации:

<?xml version="1.0" encoding="utf-8" ?>
<Configuration xmlns="https://www.unrealengine.com/BuildConfiguration">
    <BuildConfiguration>
        <StaticAnalyzer>
            PVSStudio
        </StaticAnalyzer>
    </BuildConfiguration>
</Configuration>

Исключение автогенерируемых файлов и файлов ядра Unreal Engine из анализа проекта

Файлы *.gen.cpp генерируются экосистемой Unreal Engine. Их анализ бесполезен и замедляет процесс. Также важно исключить из анализа исходники самого Unreal Engine, но это лучше делать, если вы не модифицируете движок.

Для исключения из анализа автогенерируемых файлов добавьте маску *.gen.cpp в настройку плагина PathMasks. Тут важно сказать, что начиная с Unreal Engine 5.4, анализ автогенерируемых файлов по умолчанию отключён, но если вдруг вы решили всё же проанализировать эти файлы, то можете использовать флаг -StaticAnalyzerIncludeGenerated в UBT.

Исключить из анализа модуль ядра Unreal Engine можно двумя способами:

1. Добавлением в UnrealBuildTool флага:

-StaticAnalyzerProjectOnly

2. Добавлением в файл target.cs:

bStaticAnalyzerProjectOnly = true;

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

Что нового в анализе проектов на основе Unreal Engine

Новый формат отчёта и навигация

Мы переработали формат вывода предупреждений, выдаваемых при запуске анализа через UnrealBuildTool. Наш анализатор уже давно генерирует отчёты в новом формате, и его главная фишка — поддержка многофайловой навигации. Раньше, если вы запускали анализ через UnrealBuildTool, она была недоступна, но сейчас всё работает как надо.

Распределённая сборка и анализ через Horde + UBA

В Unreal Engine 5.5 появилась удобная связка — Horde и UBA (Unreal Build Accelerator). Она умеет распределять сборку (а теперь ещё и анализ) по нескольким машинам в сети, серьёзно ускоряя весь процесс.

  • Horde — это кластерная система сборки от Epic Games, использующая MongoDB и Redis. Ставится либо через MSI, либо через Docker.

  • UBA — специальный executor, который можно включить в конфиге, чтобы задачи сборки и анализа шли параллельно на агентах.

Как подключить анализ:

  1. Разворачиваем Horde: на сервере поднимаем MongoDB и Redis, настраиваем Horde, привязываем свою учётную запись Epic Games к GitHub и принимаем инвайт в организацию.

  2. Агенты: ставим HordeAgent на нужные машины, задаём ServerUrl, Enroll и готово.

  3. Включаем анализ: в .target.cs добавляем: StaticAnalyzer = StaticAnalyzer.PVSStudio;.

  4. Настраиваем конфиг: в BuildConfiguration.xml включаем bAllowUBAExecutor, указываем нужный Server и WindowsPool.

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

Оптимизация памяти

При анализе проектов на основе Unreal Engine можно заметить, что PVS-Studio потребляет больше памяти, чем хотелось бы. Есть две основные причины:

  • Unity build (Single Compilation Unit). Unreal Engine по умолчанию объединяет кучу .cpp файлов в один большой. Это позволяет неплохо ускорить сборку, но также требует больше ресурсов для анализа.

  • Шаблоны. Unreal Engine активно использует шаблоны, а для качественного анализа нужно проводить анализ каждого инстанцирования. Это тоже даёт нагрузку.

Мы провели работу над оптимизацией ядра C и C++ анализатора, уменьшив потребление памяти и время анализа. Однако если проект большой, лучше временно отключить Unity build. Как это сделать — рассказано здесь.

Диагностические правила, специфичные для проектов на основе Unreal Engine

Ещё хочется напомнить, что в PVS-Studio доступны диагностические правила, специфичные для проектов на основе Unreal Engine:

V1100: Объявление нестатического поля класса в виде указателя на тип, унаследованный от UObject, внутри класса/структуры, которые не унаследованы от типа UObject. Сборщик мусора Unreal Engine может уничтожить объект, адресуемый этим указателем.

V1102: Объявление сущности, несоответствующей соглашениям о наименованиях для проектов на основе Unreal Engine. Соответствие этому соглашению требуется для корректной работы Unreal Header Tool.

Если у вас есть идеи по новым диагностическим правилам, мы будем рады предложениям. Более подробно об этом можно почитать здесь.

Учёт сторонних библиотек

Была занятная история: у проектов на основе Unreal Engine иногда "исчезали" срабатывания диагностических правил, включая даже наши специфичные и описанные ранее. Разобравшись, мы выяснили, что в кодовой базе движка есть файл MicrosoftPlatformCodeAnalysis.h, в котором прописаны комментарии вида //-V:: (number). Они отключают диагностические правила по всей кодовой базе, включая ваш код.

Чтобы решить проблему, мы добавили флаг --analysis-paths mode=path, который позволяет игнорировать подавления из стороннего кода. У него есть режимы:

1.mode — это набор из следующих значений:

  • skip-analysis — исключает из анализа указанные файлы и директории;

  • skip-settings — игнорирует чтение настроек из указанных файлов и директорий;

  • skip — объединяет функционал режимов skip-analysis и skip-settings;

2. path — это файлы и каталоги, к которым будут применяться настройки.

Если вы собираете проект с флагом -StaticAnalyzerProjectOnly, UnrealBuildTool сам передаёт анализатору флаг --analysis-paths с нужными параметрами. Это позволяет запустить анализ только пользовательского проекта, игнорируя модуль ядра Unreal Engine и вместе с этим все нежелательные подавления диагностических правил.

Подробнее про проблему и её устранение можно прочитать тут.

Заключение

PVS-Studio легко интегрируется в существующую сборочную систему. Чем раньше вы включите его в процесс разработки, тем меньше будет сюрпризов на релизе. А бесплатно попробовать проверить свой проект на основе Unreal Engine с помощью PVS-Studio можно по этой ссылке.

Благодарю за внимание!

Комментарии (2)


  1. Kerman
    08.08.2025 13:30

    от великого "Ведьмака" до не менее великой "The Day Before"

    Про "The Day Before" надеюсь сарказм. А Ведьмак, который великий, он на Red Engine. А тот, который на UE, тот не великий и даже ещё не вышел.


    1. 1Palych1 Автор
      08.08.2025 13:30

      The Day Before — это «величие» особого рода :)
      А Ведьмак, по-моему, в принципе не может быть не великим — у него это в ДНК.