Анализатор обнаружил в часто выполняемом коде использование аллоцирующих память методов Physics.RaycastAll
, Physics2D.OverlapSphere
или подобных им.
Такие методы создают массив при каждом вызове, что может снизить производительность. Вместо них стоит использовать неаллоцирующие вариации методов, в которые можно передать предварительно выделенный массив.
Рассмотрим пример:
public class HitScript : MonoBehaviour { void Update() { AllocMethod(); } void AllocMethod() { RaycastHit[] hitsTargets = Physics.RaycastAll(transform.position, transform.forward); foreach (RaycastHit hit in hitsTargets) { if (hit.collider.gameObject.name != "PlayerAdvanced") { .... } } } }
Update
будет каждый кадр вызывать AllocMethod
, использующий аллоцирующий метод RaycastAll
. Из-за постоянного создания новых массивов, которые содержат попадания луча, производительность ухудшится.
Данный код можно оптимизировать. Для этого нужно заменить метод RaycastAll
на неаллоцирующий метод RaycastNonAlloc
и использовать его вместе с предварительно выделенным массивом.
Вариант оптимальной реализации:
public class HitScript : MonoBehaviour { void Update() { NonAllocMethod(); } const int MAX_RAYCAST_HIT_COUNT = 10; RaycastHit[] _hitsTargets = new RaycastHit[MAX_RAYCAST_HIT_COUNT]; void NonAllocMethod() { int countOfResults = Physics.RaycastNonAlloc(new Ray(transform.position, transform.forward ), _hitsTargets); for(int i = 0; i < countOfResults; i++) { if (_hitsTargets[i].collider.gameObject.name != "PlayerAdvanced") { .... } } } }
Для использования RaycastNonAlloc
заранее создан вспомогательный массив _hitsTargets
. Максимальное количество попаданий луча ограничено размером этого массива. После вызова метода RaycastNonAlloc
количество попаданий луча будет записано в переменную countOfResults
, а сами попадания будут записаны в массив _hitsTargets
. Таким образом, в каждом кадре будет использоваться массив _hitsTargets
, под который память выделяется лишь один раз.
На момент написания документации к диагностике в классе Physics2D
все методы с припиской "NonAlloc" помечены как устаревшие, им на замену можно использовать неаллоцирующие перегрузки обычных методов. Например, вместо Physics2D.BoxCastAll
стоит использовать перегрузку Physics2D.BoxCast
, принимающую массив для получения всех попаданий.