Оптимизируем работу с физикой в Unity
14К открытий15К показов
В данном материале будет рассмотрено несколько полезных приёмов использования физики в играх и примеры их практического применения. Предполагается, что у читателя уже есть опыт разработки на Unity.
Слои и Матрица Коллизий
Все игровые объекты в Unity, если не указано иного, создаются на слое Default
, где всё со всем сталкивается, но это не очень эффективно. Однако мы можем обозначить, что с чем должно взаимодействовать, определив разные слои для разных типов объектов. Для каждого нового слоя добавляются свои строка и столбец в Матрице Коллизий, которая отвечает за определение коллизий между слоями. По умолчанию, когда вы добавляете новый слой, Матрица Коллизий определяет столкновения этого слоя со всеми остальными слоями. Путём правильной настройки слоев и Матрицы Коллизий вы избежите незапланированных столкновений и сможете тестировать события коллизий.
Для целей данной статьи была создана простая демо-сцена с 2 000 объектов (1 000 красных и 1 000 зелёных) внутри контейнера. Зелёные объекты должны взаимодействовать только сами с собой и со стенами (слой Wall
). В одном из тестов все объекты принадлежат слою Default
и столкновения производятся путём строкового сравнения тега игровых объектов на слушателе коллизий. В другом тесте объекты разделены на два слоя. Взаимодействие этих слоёв было настроено в Матрице Коллизий.
Изображение ниже берётся из самой демонстрации. В ней есть простой менеджер, который считает количество столкновений и автоматически останавливается после 5 секунд. Количество ненужных столкновений в варианте с общим слоем впечатляет.
Вот результат профилировки для более конкретных данных о физическом движке
Как мы видим, существуют значительные различия во времени, которое процессор потратил на физику. На общем слое это ~27,7 мс, а на отдельных — ~17,6 мс.
Рейкастинг
Рейкастинг — довольно полезный и мощный инструмент в физическом движке. Он позволяет направлять луч определённой длины в определённом направлении и получить информацию о произошедших столкновениях. Однако это дорогостоящая операция. Производительность рейкастинга сильно зависит от длины луча и типов коллайдеров на сцене.
Вот несколько советов по использованию рейкастинга:
- Хоть это и очевидно, но нужно стремиться к наименьшему количеству лучей.
- Не делайте лучи длиннее, чем это необходимо. Чем длиннее луч, тем больше объектов нужно проверять на столкновение с ним.
- Не используйте рейкасты внутри метода
FixedUpdate()
. А в некоторых случаях даже использование их внутри методаUpdate()
может быть излишним. - Будьте осторожнее с типами коллайдеров, которые используете. Рейкастинг с меш-коллайдером обходится довольно дорого.Неплохое решение — создать дочерний объект с примитивными коллайдерами и повторить с их помощью приблизительную форму меша. Все дочерние коллайдеры у родительского Rigidbody ведут себя как составные коллайдеры.Если вам очень нужно использовать меш-коллайдеры, то как минимум сделайте их выпуклыми.
- Уточняйте, во что именно луч должен попадать, и по возможности конкретизируйте слой-маску в функции рейкаста.Хоть это и описано в документации, но не забудьте, что то, что вы указываете в функции рейкаста, это не идентификатор слоя, а битовая маска.Если вы хотите, чтобы луч сталкивался с объектом, который находится на слое с идентификатором 10, вам необходимо указать 1<<10 (битовый сдвиг влево на 10), а не просто 10.Если вы хотите, чтобы луч врезался во всё, кроме объектов на слое 10, то просто используйте побитовый оператор дополнения (~), который инвертирует каждый бит в побитовой маске.
Вот простая демо-сцена, где объект стреляет лучами, которые сталкиваются только с зелёными объектами.
Здесь ведётся управление количеством и длиной лучей, чтобы получить данные профилировки. Мы можем увидеть на графике ниже зависимость производительности с той длиной лучей и их количеством, что мы имеем.
А вот что будет, если поменять примитивные коллайдеры на меш-коллайдеры.
Как вы можете видеть на данных профилировки, рейкастинг меш-коллайдеров заставляет физический движок работать больше.
Физика 2D vs 3D
Решите, какой физический движок лучше подходит для вашего проекта. Если вы разрабатываете 2D-игру или 2.5D (псевдотрёхмерность), то использование физического движка для 3D может быть избыточным. Дополнительное измерение в вашем проекте впустую загружает процессор. Вы можете посмотреть более детальные различия между двумя движками в статье.
Rigidbody
Компонент Rigidbody — это привычный компонент для физических взаимодействий между объектами. Даже когда вы работаете с коллайдером как с триггером, вам нужно добавить его на игровой объект для корректной работы событий OnTrigger
. Игровые объекты, которые не имеют компонента Rigidbody, рассматриваются как статические коллайдеры. Это крайне важно, т. к. попытка сдвинуть статический коллайдер крайне неэффективна, ведь движок пересчитывает весь физический мир заново. К счастью, профайлер даст вам знать, если вы попытаетесь сдвинуть статический коллайдер, и выведет предупреждение во вкладке профайлера. В следующем тесте были убраны Rigidbody со всех движущихся объектов первой демо-сцены и засняты данные профилировки, чтобы продемонстрировать, как влияют попытки сдвинуть статические коллайдеры.
Как вы можете видеть, около 2 000 предупреждений генерируется на каждом игровом объекте. Также средние затраты времени, потраченного ЦПУ на физику, возросли с ~17,6 мс до ~35,85 мс. Поэтому если мы двигаем игровой объект, важно добавить на него Rigidbody
. Если вы хотите вручную контролировать его движение, то просто пометьте его как Kinematic
в свойствах Rigidbody
.
Фиксированные временные участки (Timestep)
Настройка значения фиксированных timestep
в Time Manager непосредственно влияет на FixedUpdate()
и частоту обновления физики. Изменяя это значение, вы можете достигнуть золотой середины между точностью и временем, затраченным ЦПУ на физику.
Заключение
Все эти приёмы довольно просты в реализации, но они, несомненно, влияют на производительность вашего проекта, ведь почти каждая разрабатываемая игра использует физический движок, даже если это только обработка коллизий.
14К открытий15К показов