# V4008. Unity Engine. Avoid using memory allocation Physics APIs in performance-sensitive context.

Анализатор обнаружил в часто выполняемом коде использование аллоцирующих память методов `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`, принимающую массив для получения всех попаданий.