Version: 5.3 (switch to 5.4b)
Оптимизация производительности графики
Моделирование персонажей для оптимальной производительности

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

Для отрисовки объекта на экране движок отправляет команду (draw call) графическому API (например, OpenGL или Direct3D). Графический API производит значительную работу для каждого DC, что сильно влияет на производительность CPU.

Unity uses several techniques to address this:

  • Static Batching: combine static (i.e. not moving) objects into big meshes, and render them in a faster way.
  • Dynamic Batching: for small enough meshes, transform their vertices on the CPU, group many similar ones together, and draw in one go.

Built-in batching has several benefits compared to manually merging objects together (most notably, the objects can still be culled individually). But it also has some downsides too (static batching incurs memory and storage overhead; and dynamic batching incurs some CPU overhead).

Material Setup For Batching

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

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

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

While rendering shadow casters, they can often be batched together even if their materials are different. Shadow casters in Unity can use dynamic batching even with different materials, as long as the values in materials needed by the shadow pass are the same. For example, many crates could use materials with different textures on them, but for shadow caster rendering the textures are not relevant – in that case they can be batched together.

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

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

  • Динамический батчинг связан с дополнительной нагрузкой для каждой вершины, так что он применим только к мешам, содержащим менее 900 вершин в сумме.
  • Если ваш шейдер использует Vertex Position, Normal и единственный UV, то вы можете батчить до 300 вершин; тогда как, если шейдер использует Vertex Position, Normal, UV0, UV1 и Tangent, то только 180 вершин.
  • Обратите внимание: ограничение на количество атрибутов в будущем может быть изменено
  • Objects will not be batched if they contain mirroring on the transform, for example object A with +1 scale and object B with –1 scale can not be batched together.
  • Использование разных экземпляров материалов — даже если они по сути своей являются одним материалом — сделает динамический батчинг невозможным.
  • Объекты с картами освещения имеют дополнительное свойство: индекс карты освещения и смещение/масштаб внутри карты освещения. Для батчинга объекты должны ссылаться на одно и то же место в карте освещения.
  • Multi-pass shaders will break batching.
  • Многопроходные шейдеры могут нарушить батчинг. Почти все шейдеры Unity поддерживают несколько источников света при forward rendering, и эффективно делать дополнительный проход для них. DC для “дополнительных пиксельных источников света” не будут батчиться.
    • Legacy Deferred (light pre-pass) rendering path has dynamic batching disabled, because it has to draw objects twice.

Since it works by transforming all object vertices into world space on the CPU, it is only a win if that work is smaller than doing a “draw call”. How exactly expensive is a draw call depends on many factors, primarily on the graphics API used. For example, on consoles or modern APIs like Apple Metal the draw call overhead is generally much lower, and often dynamic batching can not be a win at all.

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

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

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

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

Internally, static batching works by transforming the static objects into world space and building a big vertex + index buffer for them. Then for visible objects in the same batch, a series of “cheap” draw calls are done, with almost no state changes in between. So technically it does not save “3D API draw calls”, but it saves on state changes done between them (which is the expensive part).

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

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

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

Manually combining objects that are close to each other might be a very good alternative to draw call batching. For example, a static cupboard with lots of drawers often makes sense to just combine into a single mesh, either in a 3D modeling application or using Mesh.CombineMeshes.

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