Многие разработчики рано или поздно сталкиваются с задачей достичь реалистичного поведения тканей или волос. Для этого есть целый ряд технологий, однако далеко не все из них подходят для мобильных платформ. Обычно мобильные разработчики запекают анимации, потому что это наименее затратно. Мы же поговорим о симуляции в реальном времени — о модуле Unity Cloth.
Unity Cloth — это система, основанная на симуляции физики тканей, которая работает вместе с SkinnedMeshRenderer. Она позволяет управлять широким набором параметров, такими как жесткость растяжения или кручения, степень затухания (величина, отвечающая за то, насколько быстро ткань придет в равновесие), симуляция ветра, взаимодействие внутренних столкновений (self-collision), трение, воздействие гравитации, влияние и взаимодействие коллайдеров и пр.
Одна из команд краснодарской студии Plarium изучила применимость Unity Cloth для мобильных устройств.
Часть 1. Симуляция тканей
Мы начали со стресс-тестов, чтобы оценить допустимые границы использования параметров модуля на мобильных устройствах. Первым исследуемым образцом стал высокополигональный многослойный меш — накидка с количеством вершин ~ 10k, треугольников ~ 7k. На объект было добавлено 19 капсульных коллайдеров по форме частей тела персонажа. Остальные настройки — по умолчанию.
На графике ниже представлена задержка исследуемых метрик в миллисекундах в зависимости от количества инстансов объекта. Тестируемое устройство — Xiaomi Mi5 (4 ядра, 2.15 ГГц, 3 ГБ ОЗУ).
Xiaomi Mi5 не самый слабый девайс, но уже на нем видны серьезные потери производительности. На менее мощных устройствах (Lenovo A536, Quad-core, 1.3 ГГц, 1 Гб ОЗУ) они становятся катастрофическими. Далее будем оценивать результаты, которые демонстрирует наиболее слабый девайс.
На одно только обновление физики тканей приходится 775 мс из 800. Попробуем исключить влияние коллайдеров.
Вычисления столкновений коллайдеров сильно снижают перфоманс, при 25 инстансах на сцене присутствовало максимум 475 коллайдеров.
Следующее измерение проведем относительно низкополигональной однослойной модели (153 вершин, 256 треугольников) с меньшим количеством инстансов (до 9) и меньшим количеством коллайдеров (до 8).
Посмотрим, какое влияние оказывают расчеты коллайдеров. Построим соответствующие зависимости на примере одного инстанса объекта на разных устройствах (помимо уже задействованных девайсов берем Asus ZenFone 5, Dual-core, 2 ГГц,1 Гб ОЗУ).
Получившиеся функции хорошо аппроксимируются полиномиальной функцией 2 степени.
Видно, что с низкополигональными объектами ситуация на порядок лучше. На самых древних устройствах на один инстанс объекта в среднем приходится около 1 мс (против ~ 3 мс для высокополигональной модели при прочих равных параметрах), что довольно неплохо.
Далее посмотрим, как влияют на производительность дополнительные параметры.
В тестах использовался однослойный меш чуть большей, чем в предыдущем измерении, детализации (~ 450 вершин, ~ 800 треугольников). В компонент Unity Cloth был добавлен 1 капсульный коллайдер, исследовался 1 инстанс объекта, варьировались дополнительные параметры внутренних столкновений и влияния ветра.
Дополнительная симуляция ветра, как и расчеты внутренних столкновений, ухудшают производительность.
Это особенно ощутимо на более сложных моделях. Проанализируем влияние дополнительных параметров жесткости (растяжение, кручение) и затухания на мешах с количеством вершин ~ 10 000 и ~ 500 с 1 капсульным коллайдером.
Ниже представлены результаты, полученные на наиболее слабом девайсе (Lenovo A536) с варьированием параметров в каждом из замеров.
1. Жесткость: Растяжение и скручивание — выкл.
Low-poly: 1.67 мс. High-poly: 145.32 мс.
2. Жесткость: Растяжение — вкл. / Скручивание — выкл.
Low-poly: 1.79 мс. High-poly: 160.44 мс.
3. Жесткость: Растяжение — выкл. / Скручивание — вкл.
Low-poly: 1.90 мс. High-poly: 172.19 мс.
4. Жесткость: Растяжение и скручивание — вкл.
Low-poly: 1.92 мс. High-poly: 194.50 мс.
5. Жесткость: Растяжение — вкл. / Скручивание — выкл. Влияние ветра — вкл.
Low-poly: 1.69 мс. High-poly: 165.73 мс.
6. Жесткость: Растяжение — вкл. / Скручивание — выкл. Затухание вкл.
Low-poly: 1.69 мс. High-poly: 172.75 мс.
7. Жесткость: Растяжение — вкл. / Скручивание — выкл. Влияние ветра — вкл. Затухание — вкл.
Low-poly: 1.76 мс. High-poly: 173.10 мс.
8. Жесткость: Растяжение — вкл. / Скручивание — выкл. Внутренние столкновения — вкл.
Low-poly: 2.01 мс. High-poly: Unity Crash
Параметры симуляции ветра, затухания, сжатия, скручивания и внутреннего взаимодействия дают дополнительную нагрузку, существенно ухудшая производительность на слабых девайсах при использовании высокополигональных мешей. У мешей с меньшим количеством вершин задержка не так велика.
- Симуляция ветра добавляет ~ 9% от общей задержки метрики.
- Симуляция затухания добавляет ~ 12% от общей задержки метрики.
- Симуляция сжатия/скручивания добавляет ~ 13–15% от общей задержки метрики.
- Симуляция внутренних взаимодействий добавляет ~ 12–16% от общей задержки метрики (при малых количествах вершин. Сделать замер с большим количеством не удалось: нагрузка оказалась слишком высокой даже для ПК).
Часть 2. Симуляция волос
Модель с ресурса cgtrader.com
Поговорим немного о возможностях компонента Unity Cloth в работе с волосами. На первый взгляд, это должно быть не сложнее, чем с однослойными тканями — сначала закрепить нужные вершины, после чего распределять степень влияния симуляции для остальных вершин. Но есть проблема — изломы объемных объектов типа локонов. Чтобы яснее увидеть причину их возникновения, возьмем гранецентрированную кубическую кристаллическую решетку какого-нибудь металла, например хлористого натрия, в качестве наглядности.
Изломы объясняются тем, что близлежащие вершины заходят за удаленные (показано стрелкой). Изломов и перекручиваний избежать не удалось даже с использованием расчетов взаимодействий внутренних столкновений. Делаем вывод, что Unity Cloth для объемных тел не подходит.
Настройки симуляции:
- Params 1: 3 коллайдера, жесткость включена на растяжение и скручивание, ветер и внутренние столкновения отключены, затухание отключено;
- Params 2: 3 коллайдера, жесткость включена на растяжение, ветер и внутренние столкновения отключены, затухание отключено;
- Params 3: 1 коллайдер, жесткость включена на растяжение, ветер и внутренние столкновения отключены, затухание отключено.
Показатели производительности двух слабых устройств сопоставимы друг с другом, Xiaomi дает лучшие результаты.
На загруженных сценах даже относительно небольшие задержки становятся существенными, а в мобильной разработке эти цифры приумножаются, так что бороться нужно за каждую десятую миллисекунды.
Краткие выводы о компоненте Unity Cloth
- Неплохо справляется с простыми однослойными объектами (флаги, накидки, покрывала и скатерти).
- При работе со сложными объектами требует высокой точности настройки.
- При работе с объемными телами дает изломы.
- Для некоторых вариантов симуляции имеющихся настроек недостаточно. Например, нельзя устанавливать свои значения гравитации: Graphics Settings используются по умолчанию.
- Применение модуля затрудняется из-за багов в некоторых версиях Unity (подробнее в разделе Bug Story).
Заключение
Симуляция простых однослойных тканей, созданная с помощью модуля Unity Cloth, довольно реалистична. Однако его стоит использовать с осторожностью: взаимодействие с большим количеством коллайдеров, как и излишние вычисления симуляции ветра, затухания, сжатия, скручивания, внутреннего взаимодействия приводят к ухудшению производительности. В целом Unity Cloth довольно ресурсозатратен для использования на мобильных устройствах, особенно это видно при симуляции тканей и волос на высокополигональных мешах.
Если вы все же намерены использовать Unity Cloth на мобильных платформах, то обратите внимание на следующие рекомендации:
- Меньше вершин — выше производительность. Используйте меши с минимально допустимым для вас количеством вершин.
- Сократите количество одновременно живущих объектов на сцене, которые подвергаются симуляции.
- Выберите минимальное количество коллайдеров, с которыми будет взаимодействовать ткань, либо, если возможно, не используйте их вообще.
- Используйте только те параметры компонента, которые необходимы для решения конкретной задачи, так как они тоже снижают производительность.
Bug Story
Вероятно, с какой-то из упомянутых ниже проблем вы уже сталкивались. По найденным багам мы формировали обращения в Unity Support.
Баг 1. В версии Unity 2018.4.4f1 компонент Cloth переопределяет Bounds в SkinnedMeshRenderer, что приводит к некорректному отображению как в редакторе, так и на устройствах.
В результате у 8 из 9 роботов пропали накидки. Ниже представлен скриншот с Xiaomi Mi 5.
Исправлено в версии 2018.4.8f1.
Баг 2. В версии 2018.4.8 в режиме редактирования Constraints улетают гизмо, из-за чего их невозможно выбрать/отметить. Точные шаги для воспроизведения бага определить не удалось, приводим примерные:
Баг исправлен в версии 2018.4.14f.
Баг 1. В версии Unity 2018.4.4f1 компонент Cloth переопределяет Bounds в SkinnedMeshRenderer, что приводит к некорректному отображению как в редакторе, так и на устройствах.
В результате у 8 из 9 роботов пропали накидки. Ниже представлен скриншот с Xiaomi Mi 5.
Исправлено в версии 2018.4.8f1.
Баг 2. В версии 2018.4.8 в режиме редактирования Constraints улетают гизмо, из-за чего их невозможно выбрать/отметить. Точные шаги для воспроизведения бага определить не удалось, приводим примерные:
- выберите объект с компонентом и войдите в режим редактирования Constraints;
- измените что-нибудь, примените изменения и выйдите из режима;
- запустите Play Mode и выйдите из него;
- откройте режим редактирования у компонента Cloth.
Баг исправлен в версии 2018.4.14f.