Оптимизация производительности графики
Моделирование персонажей для оптимальной производительности

Батчинг вызовов отрисовки (Draw Call Batching)

To draw an object on the screen, the engine has to issue a draw call to the graphics API (e.g. OpenGL or Direct3D). Draw calls are often seen as expensive, with the graphics API doing significant work for every draw call, causing performance overhead on the CPU side. However this is not the case. The expensive part is the changing of the resources accessed by the GPU between the draw calls as it triggers a graphics driver validation each time. The emphasis should be on reducing the batch count, rather than the draw call count.

Unity uses static batching to address this. The goal of the static batching is to regroup as many meshes in less buffers to get better performance, rendering giant meshes instead of a lot of small meshes which is inefficient. Unity will only loop on the same resources to render different ranges of these resources. Effectively it executes a series of fast draw calls for each staticcally batched mesh.

Встроенная поддержка батчинга в Unity имеет значительное преимущество над простым объединением геометрии в программе моделирования и перед использованием скриптов вроде идущего в пакете Standart Assets скрипта CombineChildren). Батчинг в Unity работает после этапа определения видимости. Движок обрезает каждый объект индивидуально и количество визуализируемой геометрии остаётся таким же как и без батчинга. Объединяя же геометрию в программе моделирования или иным путём, вы снижаете эффективность обрезки и, в результате, визуализируется значительно большее количество геометрии .

Материалы

Батчатся только объекты, имеющие один и тот же материал. Соответственно, для эффективного батчинга вам необходимо делать материалы общими для множества объектов, если это возможно.

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

Если нужно получить доступ к свойствам общего материала из скрипта, то важно помнить, что изменение Renderer.material приведёт к созданию копии материала. Вместо этого следует использовать свойство Renderer.sharedMaterial, чтобы материал остался общим.

Динамический батчинг (Dynamic Batching)

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

Советы:

  • Динамический батчинг связан с дополнительной нагрузкой для каждой вершины, так что он применим только к мешам, содержащим менее 900 вершин в сумме.
  • Если ваш шейдер использует Vertex Position, Normal и единственный UV, то вы можете батчить до 300 вершин; тогда как, если шейдер использует Vertex Position, Normal, UV0, UV1 и Tangent, то только 180 вершин.
  • Обратите внимание: ограничение на количество атрибутов в будущем может быть изменено
  • Как правило, объекты должны иметь один масштаб.
    • Исключение для неоднородно масштабированных объектов; если несколько объектов имеют различное неоднородное масштабирование, то они всё ещё могут батчиться.
  • Использование разных экземпляров материалов — даже если они по сути своей являются одним материалом — сделает динамический батчинг невозможным.
  • Объекты с картами освещения имеют дополнительное свойство: индекс карты освещения и смещение/масштаб внутри карты освещения. Для батчинга объекты должны ссылаться на одно и то же место в карте освещения.
  • Многопроходные шейдеры могут нарушить батчинг. Почти все шейдеры Unity поддерживают несколько источников света при forward rendering, и эффективно делать дополнительный проход для них. DC для “дополнительных пиксельных источников света” не будут батчиться.
  • Объекты, которые принимают тени в реальном времени, не батчатся.

Статический батчинг (Static Batching)

Статичный батчинг позволяет движку снизить количество DC для геометрии любого размера, если она не двигается и использует общий материал. Статичный батчинг более эффективен, чем динамический. Вы должны стараться использовать статичный батчинг, чтобы снизить нагрузку на CPU.

При использовании статичного батчинга вы должны убедиться, что объекты статичны и не двигаются, не вращаются и не масштабируются во время выполнения. Если эти условия соблюдаются, можно пометить объекты как статичные, поставив галочку Static в Inspector:

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

Static batching does not reduce batches instead of draw calls. Their number stays the same, but they are a lot faster with static batching.

Другие советы по батчингу

На данный момент, только Mesh Renderers и Particle Systems могут батчиться. Это значит, что skinned meshes, ткань, trail renderers и прочие типы рендеринг-компонентов не батчатся.

Полупрозрачные шейдеры часто требуют объектов, которые визуализируются в порядке “от заднего к переднему”, чтобы прозрачность работала корректно. Unity сначала визуализирует объекты в этом порядке и лишь затем пробует сбатчить их — так как соблюдение этого порядка очень важно, то эффективность батчинга для полупрозрачных объектов страдает по сравнению с непрозрачнымию

Некоторые части рендеринга Unity пока не поддерживают батчинг; например, батчинг не будет применяться при рендеринге объектов отбрасывающих тени, текстур глубины камеры, или GUI.

Оптимизация производительности графики
Моделирование персонажей для оптимальной производительности