Производительность Unreal — stat unit сначала, оптимизация потом
Производительность в Unreal — это методология, а не набор трюков. Правильный порядок: измерить → определить узкое место → оптимизировать именно его → измерить снова. Любое отклонение от этого алгоритма — это гадание. Кто оптимизирует «всё подряд» без stat unit, тратит дни на правки, которые не двигают FPS.
Кадр в Unreal параллельно исполняется на трёх потоках: game thread (логика, Tick, AI, Blueprints), render thread (Draw — подготовка вызовов отрисовки, отбраковка, отправка команд драйверу) и GPU (растеризация, шейдинг, post-processing). Время кадра — это максимум из трёх, а не сумма. Поэтому ускорение GPU при game-bound кадре не даёт ничего: упирается в другой поток.
Самая частая ошибка — «у меня FPS низкий, добавьте GPU» или «оптимизируем материалы». Без stat unit нельзя знать, кто виноват. Может быть, виноват один Actor с тяжёлым Tick; может быть, 5000 уникальных draw calls; может быть, две dynamic point light с теневой картой. У всех трёх причин — разные решения. Цель этой темы — научить отличать одно от другого и подобрать инструмент.
Карта темы
- Профайлинг —
stat unit,stat gpu,Unreal Insights, GPU Profiler,-trace=командная строка. - CPU vs GPU bound — определение узкого места, что значит «Game/Draw/GPU доминирует»,
r.ScreenPercentageкак тест. - Tick optimization —
bCanEverTick,SetActorTickEnabled,TickInterval,TickGroup, замена тика делегатами/таймерами. - Draw calls — что это, почему
Drawthread их выдаёт, batching, instancing, материалы-инстансы. - LOD system — LOD по дистанции/screen size, HLOD, прокси-меши, World Partition и stream-out.
- Culling — усечение по пирамиде видимости, occlusion, distance culling, cull distance volumes, dithered LOD.
- Instancing —
ISM,HISM, отличие отStaticMeshComponent, когда применять, ограничения. - Lighting cost — static/stationary/movable, dynamic shadows, light count, shadow casting, virtual shadow maps.
- UI performance — UMG invalidation,
Invalidation Box,Retainer Box, иерархия виджетов, заменаTickделегатами. - Object pooling — паттерн пула, почему
Spawn/Destroyдорогой, реализация для projectile/VFX. - Collision optimization —
TraceChannel, simple vs complex,NoCollision, фильтры, queries vs physics. - Memory profiling —
memreport,LLM,Memory Insights, стоимость GC иForceGarbageCollection.
Частые ошибки и ловушки
| Ошибка | Последствие |
|---|---|
Оптимизировать без stat unit | Тратите время не на то узкое место; FPS не меняется |
Складывать Game + Draw + GPU | Это параллельные потоки, кадр = max, а не сумма |
Оставлять bCanEverTick = true по умолчанию для всех акторов | Тысячи пустых тиков съедают game thread |
Спавнить projectile через SpawnActor каждый выстрел | Тяжёлые аллокации, GC давление; нужен пул |
| Ставить dynamic point light без необходимости | Каждый источник с тенями — отдельный shadow pass на GPU |
Использовать StaticMeshComponent для 5000 камней | Каждый — отдельный draw call; нужен HISM |
Делать Event Tick в UMG-виджете | Перерисовка слоя UI каждый кадр; нужен delegate-driven update |
| Считать LOD автоматическим для любого меша | LOD'ы должны быть созданы для конкретного ассета |
Тестировать GPU bottleneck на 4K без r.ScreenPercentage | Не отделяете влияние разрешения от шейдеров |
LineTraceByChannel каждый кадр на каждом враге | Десятки запросов в physics scene; кэшируйте, фильтруйте |
Думать, что Destroy() сразу освобождает память | Объект попадает в GC, освобождение отложено до следующего цикла |
| Профилировать в редакторе и делать выводы про packaged build | Editor содержит overhead инструментов и slate, цифры нерелевантны |
Значение для собеседований
Производительность — senior-тема. Проверяется:
- Знание
stat unitи интерпретация трёх потоков (Game/Draw/GPU). - Канонический алгоритм: профайл → bottleneck → точечная правка → повторный замер.
- Умение отличить CPU-bound от GPU-bound и предложить разные решения.
- Знание, почему
ISM/HISMснижаютdraw calls, а не «нагрузку GPU вообще». - Знание стоимости dynamic shadow vs static light.
- Знание pool-паттерна и почему
SpawnActorдорогой.
Типичный неверный ответ: «Я оптимизирую материалы, ставлю LOD'ы и всё работает быстро». Реальный ответ — без диагностики неизвестно, что узкое место. У сцены с 200 dynamic lights и одним материалом проблема не в материале; у сцены с 50000 уникальных мешей без LOD проблема не в свете. Сначала stat unit, потом разговор.