Physics.SphereCastNonAlloc - extremly slow depending on array size

Hello,

I replace my Physics.SphereCastAll with a Physics.SphereCastNonAlloc.
I noticed a significant framerate drop when doing so.

I allocate the array only once:

private RaycastHit[] m_groundRaycastHits = new RaycastHit[10];

And use it in the FixedUpdate like this:

int hitsCount = Physics.SphereCastNonAlloc(castOrigin, radius, castDirection, m_groundRaycastHits, castLength, groundCheckMask);

I started to investigate why the framerate was dropping and found out that the bigger the size of the array was the lower the framerate. Just for fun I used an array of 10000 elements, and the framerate was dropping to 1 frame every 30 seconds.

I naively though the array size wouldn’t matter that much but it actually does a lot. Any idea ?

I did a test and I am not seeing any noticeable difference.
Can we see the rest of your code, or maybe you can give us a script that will demonstrate the issue better?

This was my test
Click for code

using UnityEngine;
using System.Diagnostics;

public class TestCastLag : MonoBehaviour
{
    public int arraySize = 10000;

    RaycastHit[] hitInfos;
    float currentSize;

    Stopwatch stopWatch = new Stopwatch();
    int averageLoop = 50;

    //Enable and disable in inspector to run again.
    //Ignore the first result after hitting play since I think the lag of first hitting play messes things up.
    void OnEnable()
    {
        if(arraySize != currentSize) SetArray();

        stopWatch.Reset();
        stopWatch.Start();

        double average = 0;
        for(int i = 0; i < averageLoop; i++)
        {
            int count = Physics.SphereCastNonAlloc(transform.position, .5f, -transform.up, hitInfos, 10000, Physics.AllLayers);
            stopWatch.Stop();
            average += stopWatch.Elapsed.TotalMilliseconds;
        }
        average /= averageLoop;

        UnityEngine.Debug.Log("Array size = " + hitInfos.Length + " Stopwatch average result = " + average + " Milliseconds");
    }

    void SetArray()
    {
        hitInfos = new RaycastHit[arraySize];
        currentSize = hitInfos.Length;
    }
}

An array size of 10000 and an array size of 1 both resulted in an average of about .035 milliseconds with the code above.
I have the code in OnEnable so that I could get more consistent results (Ignore the first result after hitting play since I think the lag of first hitting play messes things up), but I also ran the code in Update and saw no drop in frames or anything.

Are you able to reproduce this in a new project and post it here for us to check out?

In case you dont know, there is also a profiler to get a better idea of what is causing lag

You can click “Deep Profile” to get an even better idea.

Well sorry I was wrong. I assumed it was Physics.SphereCastNonAlloc that was causing the issue because it was the only code I changed. But turns out a Array.Sort was also performed on the array. And this sort was using the array length and not the hitCount returned by Physics.SphereCastNonAlloc. Sorry again. Thanks for your awnser!

3 Likes