RayCast performance problem

Hi guys, I have an environment with almost 400 cars and every car contains 9 sensors. Everytime when my car detect something i use return to avoid using another RayCast, but still I have problems:

 private void prioritySensors()
    {
        if (_currentWayPoint == null)
            return;
        if (Intersection)
            _intersectionAhead = false;

        _reverse = false;
        CarAhead = "";
        _priority = false;
        _isCarAhead = false;

        FrontCenterSensorPriority = false;
        FrontLeftSensorPriority = false;
        FrontObliqueLeftSensorPriority = false;
        FrontRightSensorPriority = false;
        FrontObliqueRightSensorPriority = false;
        LeftSideSensorPriority = false;
        RightSideSeonsorPriority = false;
        BackLeftSensorPriority = false;
        BackRightSensorPriority = false;

        // dimensiunea senzorului va fi adaptata in functie de viteza
        float newFrontSensorsLength = 0;
        // speed 15 -------------- FrontSL
        // speed x  -------------- newFrontSL
        if (CurrentSpeed > 100)
            newFrontSensorsLength = 40;
        else if (CurrentSpeed > 80)
            newFrontSensorsLength = 35;
        else if (CurrentSpeed > 60)
            newFrontSensorsLength = 30;
        else if (CurrentSpeed > 40)
            newFrontSensorsLength = 25;
        else if (CurrentSpeed > 30)
            newFrontSensorsLength = 20;
        else if (CurrentSpeed > 20)
            newFrontSensorsLength = 15;
        else if (CurrentSpeed > 15)
            newFrontSensorsLength = 10;
        else
            newFrontSensorsLength = 3;
        if (Intersection)
            newFrontSensorsLength += 2;

        // Stabilim dimensiunea senzorilor in intersectii
        float newFronSideSensorsLength = FrontSideSensorsLength;
        float newFrontObliqSensorsAngle = FrontObliqSensorsAngle;
        if (RoundAbout)
            newFronSideSensorsLength *= 1.5f;
        else if (Intersection && !GoRight)
        {
            newFronSideSensorsLength = 12;
            if (GoForward)
            {
                newFronSideSensorsLength = 8;
                newFrontObliqSensorsAngle = 5;
            }

        }
        float dim = FrontSideSensorsLength;

        RaycastHit hit = new RaycastHit();
        Color colorSensor = new Color();
        colorSensor = Color.green;

        Vector3 frontSensorsStartPosition = transform.position;
        frontSensorsStartPosition += transform.forward * FrontSensorsPosition.z; // are aceeasi directie ca si masina
        frontSensorsStartPosition += transform.up * FrontSensorsPosition.y; // se afla la aceeasi inaltime indiferent de pozitia masinii

        Vector3 sideSensorsStartPosition = transform.position;
        sideSensorsStartPosition += transform.forward * SideSensorsPosition.z; // are aceeasi directie ca si masina
        sideSensorsStartPosition += transform.up * SideSensorsPosition.y; // se afla la aceeasi inaltime indiferent de pozitia masinii

        Vector3 backObliqSensorsStartPosition = transform.position;
        backObliqSensorsStartPosition += transform.forward * (-1) * BackSensorsPosition.z; // are aceeasi directie ca si masina
        backObliqSensorsStartPosition += transform.up * BackSensorsPosition.y; // se afla la aceeasi inaltime indiferent de pozitia masinii

        RaycastHit[] hits;
        hits = Physics.RaycastAll(frontSensorsStartPosition, transform.forward, newFrontSensorsLength);
        // Front Center
        bool hited = false;
        if (hits.Length > 0)
        {
            foreach (var h in hits)
            {
                // reduc viteza in intersectii
                if (h.collider.gameObject.CompareTag("Intersection"))
                {
                    _intersectionAhead = true;
                    if (CurrentSpeed > 30)
                    {
                        _isCarAhead = true;
                        return;
                    }
                }
                if (h.collider.gameObject.CompareTag("Car"))
                {
                    hit = h;
                    hited = true;
                    break;
                }
            }
            if (hited)
            {
                FrontCenterSensorPriority = true;

                //Debug.DrawLine(frontSensorsStartPosition, hit.point, colorSensor);
                CarAhead = hit.collider.gameObject.name;
                if (hit.collider.CompareTag("Player"))
                {
                    _isCarAhead = true;
                    return;
                }

                _priority = getPriority(hit.collider.gameObject, hit);
                _isCarAhead = !_priority;
                return;
            }

        }

        // Front Left
        frontSensorsStartPosition -= transform.right * FrontObliqSensorsPosition;
        dim = (Intersection && !GoRight) ? newFronSideSensorsLength : newFrontSensorsLength + 1;
        if (Physics.Raycast(frontSensorsStartPosition, transform.forward, out hit, dim))
        {
            if (!hit.collider.CompareTag("WayPoint") && !hit.collider.CompareTag("NotForSensors") && !hit.collider.CompareTag("Intersection"))
            {
                //Debug.Log("FL Dim: " + dim + " NewLength" + newFrontSensorsLength + " Inter: " + newFronSideSensorsLength);
                FrontLeftSensorPriority = true;

                Debug.DrawLine(frontSensorsStartPosition, hit.point, colorSensor);
                CarAhead = hit.collider.gameObject.name;

                if (hit.collider.CompareTag("Player"))
                {
                    _isCarAhead = true;
                    return;
                }

                _priority = getPriority(hit.collider.gameObject, hit);
                _isCarAhead = !_priority;
                return;

            }
        }

        // Oblique Left       
        dim = (Intersection && !GoRight) ? newFronSideSensorsLength : FrontSideSensorsLength;
        if (Physics.Raycast(frontSensorsStartPosition, Quaternion.AngleAxis(-newFrontObliqSensorsAngle, transform.up) * transform.forward, out hit, dim))
        {
            if (!hit.collider.CompareTag("WayPoint") && !hit.collider.CompareTag("NotForSensors") && !hit.collider.CompareTag("Intersection"))
            {
                //Debug.Log("OL Dim: " + dim + " NewLength" + FrontSideSensorsLength + " Inter: " + newFronSideSensorsLength);
                FrontObliqueLeftSensorPriority = true;

                Debug.DrawLine(frontSensorsStartPosition, hit.point, colorSensor);
                CarAhead = hit.collider.gameObject.name;

                if (hit.collider.CompareTag("Player"))
                {
                    _isCarAhead = true;
                    return;
                }

                _priority = getPriority(hit.collider.gameObject, hit);
                _isCarAhead = !_priority;
                return;

            }
        }

        // Front Right
        frontSensorsStartPosition += 2 * transform.right * FrontObliqSensorsPosition;
        dim = (Intersection && !GoRight) ? newFronSideSensorsLength : newFrontSensorsLength + 1;
        if (Physics.Raycast(frontSensorsStartPosition, transform.forward, out hit, dim))
        {
            if (!hit.collider.CompareTag("WayPoint") && !hit.collider.CompareTag("NotForSensors") && !hit.collider.CompareTag("Intersection"))
            {
                //Debug.Log("FR Dim: " + dim + " NewLength" + newFrontSensorsLength + " Inter: "+ newFronSideSensorsLength);

                FrontRightSensorPriority = true;

                Debug.DrawLine(frontSensorsStartPosition, hit.point, colorSensor);
                CarAhead = hit.collider.gameObject.name;

                if (hit.collider.CompareTag("Player"))
                {
                    _isCarAhead = true;
                    return;
                }

                _priority = getPriority(hit.collider.gameObject, hit);
                _isCarAhead = !_priority;
                return;
            }
        }

        // Oblique Right     
        dim = (Intersection && !GoRight) ? newFronSideSensorsLength : FrontSideSensorsLength;
        if (Physics.Raycast(frontSensorsStartPosition, Quaternion.AngleAxis(FrontObliqSensorsAngle, transform.up) * transform.forward, out hit, dim))
        {
            if (!hit.collider.CompareTag("WayPoint") && !hit.collider.CompareTag("NotForSensors") && !hit.collider.CompareTag("Intersection"))
            {
                //Debug.Log("OR Dim: " + dim + " NewLength" + FrontSideSensorsLength + " Inter: " + newFronSideSensorsLength);
                FrontObliqueRightSensorPriority = true;

                Debug.DrawLine(frontSensorsStartPosition, hit.point, colorSensor);
                CarAhead = hit.collider.gameObject.name;

                if (hit.collider.CompareTag("Player"))
                {
                    _isCarAhead = true;
                    return;

                }
                _priority = getPriority(hit.collider.gameObject, hit);
                _isCarAhead = !_priority;
                return;
            }
        }

        // RIGHT SIDE
        sideSensorsStartPosition += transform.right * SidePosition;
        if (!Intersection && (Mathf.Abs(_targetSteerAngle) > 7) || (Mathf.Abs(_dirAngle) > 10 && (_distance < 2)))
        {
            if (Physics.Raycast(sideSensorsStartPosition, Quaternion.AngleAxis(90, transform.up) * transform.forward, out hit, SideSensorsLength))
            {
                if (!hit.collider.CompareTag("WayPoint") && !hit.collider.CompareTag("NotForSensors") && !hit.collider.CompareTag("Intersection"))
                {
                    RightSideSeonsorPriority = true;

                    Debug.DrawLine(sideSensorsStartPosition, hit.point, colorSensor);
                    CarAhead = hit.collider.gameObject.name;

                    if (hit.collider.CompareTag("Player"))
                    {
                        _isCarAhead = true;
                        return;
                    }

                    _priority = getPriority(hit.collider.gameObject, hit);
                    _isCarAhead = !_priority;
                    return;
                }
            }
        }


        // LEFT SIDE
        sideSensorsStartPosition -= 2 * transform.right * SidePosition;
        if (!Intersection && (Mathf.Abs(_targetSteerAngle) > 7 || (Mathf.Abs(_dirAngle) > 10 && (_distance < 2))))
        {
            if (Physics.Raycast(sideSensorsStartPosition, Quaternion.AngleAxis(-90, transform.up) * transform.forward, out hit, SideSensorsLength))
            {
                if (!hit.collider.CompareTag("WayPoint") && !hit.collider.CompareTag("NotForSensors") && !hit.collider.CompareTag("Intersection"))
                {
                    LeftSideSensorPriority = true;

                    Debug.DrawLine(sideSensorsStartPosition, hit.point, colorSensor);
                    CarAhead = hit.collider.gameObject.name;

                    if (hit.collider.CompareTag("Player"))
                    {
                        _isCarAhead = true;
                        return;
                    }

                    _priority = getPriority(hit.collider.gameObject, hit);
                    _isCarAhead = !_priority;
                    return;
                }
            }

        }


        // RIGHT OBLIQUE BACK
        if (GoRight && !Intersection && _distance < 3)
        {
            backObliqSensorsStartPosition += transform.right * BackObliqSensorsPosition;
            // Acest senzor se activeaza atunci cand masina isi schimba banda
            if (Physics.Raycast(backObliqSensorsStartPosition, Quaternion.AngleAxis(BackObliqSensorsAngle, transform.up) * transform.forward, out hit, BackObliqSensorsLength))
            {
                //Debug.Log("RIGHT");
                if (!hit.collider.CompareTag("WayPoint") && !hit.collider.CompareTag("NotForSensors") && !hit.collider.CompareTag("Intersection"))
                {

                    BackRightSensorPriority = true;

                    Debug.DrawLine(backObliqSensorsStartPosition, hit.point, colorSensor);
                    CarAhead = hit.collider.gameObject.name;

                    if (hit.collider.CompareTag("Player"))
                    {
                        _isCarAhead = true;
                        return;
                    }

                    _priority = getPriority(hit.collider.gameObject, hit);
                    _isCarAhead = !_priority;
                    return;
                }
            }
        }

        // LEFT OBLIQUE BACK
        if (GoLeft && !Intersection && _distance < 3)
        {
            backObliqSensorsStartPosition -= 2 * transform.right * BackObliqSensorsPosition;
            if (Physics.Raycast(backObliqSensorsStartPosition, Quaternion.AngleAxis(-BackObliqSensorsAngle, transform.up) * transform.forward, out hit, BackObliqSensorsLength))
            {
                //Debug.Log("LEFT");
                if (!hit.collider.CompareTag("WayPoint") && !hit.collider.CompareTag("NotForSensors") && !hit.collider.CompareTag("Intersection"))
                {
                    BackLeftSensorPriority = true;

                    Debug.DrawLine(backObliqSensorsStartPosition, hit.point, colorSensor);
                    CarAhead = hit.collider.gameObject.name;

                    if (hit.collider.CompareTag("Player"))
                    {
                        _isCarAhead = true;
                        return;
                    }

                    _priority = getPriority(hit.collider.gameObject, hit);
                    _isCarAhead = !_priority;
                    return;
                }
            }
        }

    }

Well, of the 90ms that FixedUpdate took that frame, only 9ms was your actual raycasting. Note that because the overall framerate was so low, Unity had to run FixedUpdate 5 times that frame. I’d be curious what the other 80ms in FixedUpdate was.

Anyway, if you really want to improve FixedUpdate performance, the recommended approach is to use RaycastCommand to perform your raycasts as a job, which gets spread out over all threads.

I use this approach, and it made a big difference in places where I’m doing lots of raycasting.

Thank you,
For now i dont understand how to use it, but I will try.

I got this:
A Native Collection has not been disposed, resulting in a memory leak. It was allocated at C:\Users\zzava\Desktop\Licenta\TrafficSimulator\Assets\Scripts\CarAI\CarEngine.cs:451.

 var results = new NativeArray<RaycastHit>(1, Allocator.Temp);
        var commands = new NativeArray<RaycastCommand>(1, Allocator.Temp);


        Vector3 frontSensorsStartPosition = transform.position;
        frontSensorsStartPosition += transform.forward * FrontSensorsPosition.z; // are aceeasi directie ca si masina
        frontSensorsStartPosition += transform.up * FrontSensorsPosition.y; // se afla la aceeasi inaltime indiferent de pozitia masinii

        Vector3 sideSensorsStartPosition = transform.position;
        sideSensorsStartPosition += transform.forward * SideSensorsPosition.z; // are aceeasi directie ca si masina
        sideSensorsStartPosition += transform.up * SideSensorsPosition.y; // se afla la aceeasi inaltime indiferent de pozitia masinii

        Vector3 backObliqSensorsStartPosition = transform.position;
        backObliqSensorsStartPosition += transform.forward * (-1) * BackSensorsPosition.z; // are aceeasi directie ca si masina
        backObliqSensorsStartPosition += transform.up * BackSensorsPosition.y; // se afla la aceeasi inaltime indiferent de pozitia masinii

        commands[0] = new RaycastCommand(frontSensorsStartPosition, transform.forward);
        // Schedule the batch of raycasts
        JobHandle handle = RaycastCommand.ScheduleBatch(commands, results, 1, default(JobHandle));

        // Wait for the batch processing job to complete
        handle.Complete();

        // Copy the result. If batchedHit.collider is null there was no hit
        RaycastHit batchedHit = results[0];

        //RaycastHit[] hits;
         //hits = Physics.RaycastAll(frontSensorsStartPosition, transform.forward, newFrontSensorsLength);
        // Front Center
        bool hited = false;
        if (results.Length > 0)
        {
            foreach (var h in results)
            {
                // reduc viteza in intersectii
                if (h.collider.gameObject.CompareTag("Intersection"))
                {
                    _intersectionAhead = true;
                    if (CurrentSpeed > 30)
                    {
                        _isCarAhead = true;
                        return;
                    }
                }
                if (h.collider.gameObject.CompareTag("Car"))
                {
                    hit = h;
                    hited = true;
                    break;
                }
            }
            if (hited)
            {
                FrontCenterSensorPriority = true;

                //Debug.DrawLine(frontSensorsStartPosition, hit.point, colorSensor);
                CarAhead = hit.collider.gameObject.name;
                if (hit.collider.CompareTag("Player"))
                {
                    _isCarAhead = true;
                    return;
                }

                _priority = getPriority(hit.collider.gameObject, hit);
                _isCarAhead = !_priority;
                return;
            }

        }

        // Dispose the buffers
        results.Dispose();
        commands.Dispose();

Possibly similar to this?

Is this happening frequently, or when you stop the game or change something? I dispose of my native arrays immediately after being done with them, but I also dispose of them in OnDestroy and OnDisable, just in case the job was running when I stopped the game or unloaded the scene.

I used return, that was the mistake.

But now, can I use RaycastCommand instead RaycastAll ?
I want that my raycast to seed two objects, intersection and car.

And raycastCommand, doesn’t have a maxim length? I want to use it for few meters.

RaycastCommand has a ‘distance’ property you can set, to control the length of the cast.

I’m not sure the best approach to finding two hits, but my guess is it might make more sense to add pairs of RaycastCommands, one for the ‘car’ layer and one for the ‘intersection’ layer. Or the same thing, but ignoring the the car and intersection layers respectively.

Alternatively, you could create a Job to do everything. RaycastCommand is a kind of job that Unity has created for convenience, but if it’s not quite right for you then doing the complex processing with a custom Job would be the way to go. The point of Jobs is that they use all available processors to do the work.

IS better now?

  bool hited = false;

        #region Sensor - Front-Center
        // Front Center
        RaycastHit[] hits;
        hits = Physics.RaycastAll(frontSensorsStartPosition, transform.forward, newFrontSensorsLength);
        if (hits.Length > 0)
        {
            foreach (var h in hits)
            {
                // reduc viteza in intersectii
                if (h.collider.gameObject.CompareTag("Intersection"))
                {
                    _intersectionAhead = true;
                    if (CurrentSpeed > 30)
                    {
                        _isCarAhead = true;
                        return;
                    }
                }
                if (h.collider.gameObject.CompareTag("Car"))
                {
                    hit = h;
                    hited = true;
                    break;
                }
            }
            if (hited)
            {
                FrontCenterSensorPriority = true;

                Debug.DrawLine(frontSensorsStartPosition, hit.point, colorSensor);
                CarAhead = hit.collider.gameObject.name;
                if (hit.collider.CompareTag("Player"))
                {
                    _isCarAhead = true;
                    return;
                }

                _priority = getPriority(hit.collider.gameObject, hit);
                _isCarAhead = !_priority;
                return;
            }

        }
        #endregion

        var results = new NativeArray<RaycastHit>(1, Allocator.Temp);
        var commands = new NativeArray<RaycastCommand>(1, Allocator.Temp);

        #region Sensor - Front Left
        if (!hited)
        {
            frontSensorsStartPosition -= transform.right * FrontObliqSensorsPosition;
            dim = (Intersection && !GoRight) ? newFronSideSensorsLength : newFrontSensorsLength + 1;

            commands[0] = new RaycastCommand(frontSensorsStartPosition, transform.forward, dim);
            JobHandle handle = RaycastCommand.ScheduleBatch(commands, results, 1, default(JobHandle));
            handle.Complete();
            RaycastHit batchedHit = results[0];

            if ((batchedHit.collider) && !batchedHit.collider.CompareTag("WayPoint") && !batchedHit.collider.CompareTag("NotForSensors") && !batchedHit.collider.CompareTag("Intersection"))
            {
                hited = true;
                FrontLeftSensorPriority = true;

                Debug.DrawLine(frontSensorsStartPosition, batchedHit.point, colorSensor);
                CarAhead = batchedHit.collider.gameObject.name;

                if (batchedHit.collider.CompareTag("Player"))
                    _isCarAhead = true;

                else
                {
                    _priority = getPriority(batchedHit.collider.gameObject, batchedHit);
                    _isCarAhead = !_priority;
                }
            }
        }
        #endregion

        #region Sensor - Front Left Oblique
        if (!hited)
        {
            dim = (Intersection && !GoRight) ? newFronSideSensorsLength : FrontSideSensorsLength;

            commands[0] = new RaycastCommand(frontSensorsStartPosition, Quaternion.AngleAxis(-newFrontObliqSensorsAngle, transform.up) * transform.forward, dim);
            JobHandle handle = RaycastCommand.ScheduleBatch(commands, results, 1, default(JobHandle));
            handle.Complete();
            RaycastHit batchedHit = results[0];

            if ((batchedHit.collider) && (batchedHit.collider) && !batchedHit.collider.CompareTag("WayPoint") && !batchedHit.collider.CompareTag("NotForSensors") && !batchedHit.collider.CompareTag("Intersection"))
            {
                hited = true;
                FrontObliqueLeftSensorPriority = true;

                Debug.DrawLine(frontSensorsStartPosition, batchedHit.point, colorSensor);
                CarAhead = batchedHit.collider.gameObject.name;

                if (batchedHit.collider.CompareTag("Player"))
                    _isCarAhead = true;
                else
                {
                    _priority = getPriority(batchedHit.collider.gameObject, batchedHit);
                    _isCarAhead = !_priority;
                }
            }
        }
        #endregion

        #region Sensor - Front Right
        if (!hited)
        {
            frontSensorsStartPosition += 2 * transform.right * FrontObliqSensorsPosition;
            dim = (Intersection && !GoRight) ? newFronSideSensorsLength : newFrontSensorsLength + 1;

            commands[0] = new RaycastCommand(frontSensorsStartPosition, transform.forward, dim);
            JobHandle handle = RaycastCommand.ScheduleBatch(commands, results, 1, default(JobHandle));
            handle.Complete();
            RaycastHit batchedHit = results[0];

            if ((batchedHit.collider) && !batchedHit.collider.CompareTag("WayPoint") && !batchedHit.collider.CompareTag("NotForSensors") && !batchedHit.collider.CompareTag("Intersection"))
            {
                hited = true;
                FrontRightSensorPriority = true;

                Debug.DrawLine(frontSensorsStartPosition, batchedHit.point, colorSensor);
                CarAhead = batchedHit.collider.gameObject.name;

                if (batchedHit.collider.CompareTag("Player"))
                    _isCarAhead = true;
                else
                {
                    _priority = getPriority(batchedHit.collider.gameObject, batchedHit);
                    _isCarAhead = !_priority;
                } 
            }
        }
        #endregion

        #region Sensor - Front Right Oblique
        if (!hited)
        {
            dim = (Intersection && !GoRight) ? newFronSideSensorsLength : FrontSideSensorsLength;

            commands[0] = new RaycastCommand(frontSensorsStartPosition, Quaternion.AngleAxis(FrontObliqSensorsAngle, transform.up) * transform.forward, dim);
            JobHandle handle = RaycastCommand.ScheduleBatch(commands, results, 1, default(JobHandle));
            handle.Complete();
            RaycastHit batchedHit = results[0];

            if ((batchedHit.collider) && !batchedHit.collider.CompareTag("WayPoint") && !batchedHit.collider.CompareTag("NotForSensors") && !batchedHit.collider.CompareTag("Intersection"))
            {
                hited = true;
                FrontObliqueRightSensorPriority = true;

                Debug.DrawLine(frontSensorsStartPosition, batchedHit.point, colorSensor);
                CarAhead = batchedHit.collider.gameObject.name;

                if (batchedHit.collider.CompareTag("Player"))
                    _isCarAhead = true;
                else
                {
                    _priority = getPriority(batchedHit.collider.gameObject, batchedHit);
                    _isCarAhead = !_priority;
                }
            }
        }
        #endregion

        #region Sensor - Side Left
        if (!Intersection && (Mathf.Abs(_targetSteerAngle) > 7 || (Mathf.Abs(_dirAngle) > 10 && (_distance < 2))))
        {
            if (!hited)
            {
                sideSensorsStartPosition -= transform.right * SidePosition;

                commands[0] = new RaycastCommand(sideSensorsStartPosition, Quaternion.AngleAxis(-90, transform.up) * transform.forward, SideSensorsLength);
                JobHandle handle = RaycastCommand.ScheduleBatch(commands, results, 1, default(JobHandle));
                handle.Complete();
                RaycastHit batchedHit = results[0];

                if ((batchedHit.collider) && !batchedHit.collider.CompareTag("WayPoint") && !batchedHit.collider.CompareTag("NotForSensors") && !batchedHit.collider.CompareTag("Intersection"))
                {
                    hited = true;
                    LeftSideSensorPriority = true;

                    Debug.DrawLine(sideSensorsStartPosition, batchedHit.point, colorSensor);
                    CarAhead = batchedHit.collider.gameObject.name;

                    if (batchedHit.collider.CompareTag("Player"))
                        _isCarAhead = true;
                    else
                    {
                        _priority = getPriority(batchedHit.collider.gameObject, batchedHit);
                        _isCarAhead = !_priority;
                    }
                }
            }

        }
        #endregion

        #region Sensor - Side Right
        if (!Intersection && (Mathf.Abs(_targetSteerAngle) > 7) || (Mathf.Abs(_dirAngle) > 10 && (_distance < 2)))
        {
            if (!hited)
            {
                sideSensorsStartPosition += 2 * transform.right * SidePosition;

                commands[0] = new RaycastCommand(sideSensorsStartPosition, Quaternion.AngleAxis(90, transform.up) * transform.forward, SideSensorsLength);
                JobHandle handle = RaycastCommand.ScheduleBatch(commands, results, 1, default(JobHandle));
                handle.Complete();
                RaycastHit batchedHit = results[0];

                if ( (batchedHit.collider) && !batchedHit.collider.CompareTag("WayPoint") && !batchedHit.collider.CompareTag("NotForSensors") && !batchedHit.collider.CompareTag("Intersection"))
                {
                    hited = true;
                    RightSideSeonsorPriority = true;

                    Debug.DrawLine(sideSensorsStartPosition, batchedHit.point, colorSensor);
                    CarAhead = batchedHit.collider.gameObject.name;

                    if (batchedHit.collider.CompareTag("Player"))
                        _isCarAhead = true;
                    else
                    {
                        _priority = getPriority(batchedHit.collider.gameObject, batchedHit);
                        _isCarAhead = !_priority;
                    }
                }
            }
        }
        #endregion

        #region Sensor - Back Left Oblique
        if (GoLeft && !Intersection && _distance < 3)
        {
            backObliqSensorsStartPosition -= 2 * transform.right * BackObliqSensorsPosition;
            if (!hited)
            {

                commands[0] = new RaycastCommand(backObliqSensorsStartPosition, Quaternion.AngleAxis(-BackObliqSensorsAngle, transform.up) * transform.forward, BackObliqSensorsLength);
                JobHandle handle = RaycastCommand.ScheduleBatch(commands, results, 1, default(JobHandle));
                handle.Complete();
                RaycastHit batchedHit = results[0];

                if ((batchedHit.collider) && !batchedHit.collider.CompareTag("WayPoint") && !batchedHit.collider.CompareTag("NotForSensors") && !batchedHit.collider.CompareTag("Intersection"))
                {
                    hited = true;
                    BackLeftSensorPriority = true;

                    Debug.DrawLine(backObliqSensorsStartPosition, batchedHit.point, colorSensor);
                    CarAhead = batchedHit.collider.gameObject.name;

                    if (batchedHit.collider.CompareTag("Player"))
                        _isCarAhead = true;
                    else
                    {
                        _priority = getPriority(batchedHit.collider.gameObject, batchedHit);
                        _isCarAhead = !_priority;
                    }
                }
            }
        }
        #endregion

        #region Sensor - Back Right Oblique
        if (GoRight && !Intersection && _distance < 3)
        { 
            if (!hited)
            {
                backObliqSensorsStartPosition += transform.right * BackObliqSensorsPosition;

                commands[0] = new RaycastCommand(backObliqSensorsStartPosition, Quaternion.AngleAxis(BackObliqSensorsAngle, transform.up) * transform.forward, BackObliqSensorsLength);
                JobHandle handle = RaycastCommand.ScheduleBatch(commands, results, 1, default(JobHandle));
                handle.Complete();
                RaycastHit batchedHit = results[0];

                if ((batchedHit.collider) && !batchedHit.collider.CompareTag("WayPoint") && !batchedHit.collider.CompareTag("NotForSensors") && !batchedHit.collider.CompareTag("Intersection"))
                {
                    hited = true;
                    BackRightSensorPriority = true;

                    Debug.DrawLine(backObliqSensorsStartPosition, batchedHit.point, colorSensor);
                    CarAhead = batchedHit.collider.gameObject.name;

                    if (batchedHit.collider.CompareTag("Player"))
                        _isCarAhead = true;
                    else
                    {
                        _priority = getPriority(batchedHit.collider.gameObject, batchedHit);
                        _isCarAhead = !_priority;
                    }
                }
            }
        }
        #endregion

        // Dispose the buffers
        results.Dispose();
        commands.Dispose();

No, that’s probably not better. The whole point of RaycastCommand is that you can add LOTS of raycasts to a single call to RaycastCommand.ScheduleBatch, and those raycasts will be performed across all available threads. To me, it looks like you’re just putting one RaycastCommand per batch, which wouldn’t be likely to get your any better performance, and I imagine might even make things slower.

I realize using RaycastCommand isn’t super trivial. It might mean significantly changing the approach you’ve been taking. Right now it seems you go through each car, one at a time, and perform its raycasts, before moving on to the next car. To improve performance, you’ll probably need to batch all of those cars into a single (or a small number of ) RaycastCommand.ScheduleBatch calls, and then loop through the results again after to evaluate all of the raycast hit results.

Now, if my car see something then I have a raycastCommand with one raycast, but if I add a lot of raycasts I will have a raycastCommand with a lot of raycasts, for me it seems worst.

That’s not how RaycastCommand works. In your original post, your profiler results show that you performed more than 8000 raycasts in a single frame. All of those raycasts were performed on the main thread, meaning that all the other cores of your CPU didn’t help out.

Using RaycastCommands, you could potentially spread those 8000 raycasts out across all CPUs, so that they finish much faster. The challenge is writing your code in a way where you can batch up the raycasts into these jobs, run the job, and then evaluate the results after. Ideally you’d run a single RaycastCommand.ScheduleBatch per FixedUpdate, with all of the necessary RaycastCommands in it.

And call the raycastCommand at every frame? Sound interesting

Yes. Well, not every frame, but every FixedUpdate. Or as often as you need to. In my case, I’m using raycasts to decide how much force to apply to a large number of rigidbodies, so I do the raycasting every FixedUpdate. I could probably get away with doing it every other FixedUpdate, and caching the results, but so far with RaycastCommands there aren’t any performance issues doing it every FixedUpdate. Of course, if you don’t need to do the raycast for a particular object in a particular FixedUpdate it would be best to avoid doing so.

I think now is worst,

With deep profiler

Like I said, now you’re calling RaycastCommand.ScheduleBatching about 4000 times per fixed update. You should be trying to call it once per fixed update. And again, if you want to try to get the performance improvements out of this, it will involved some restructuring of your code.

I don’t understand very good. You say should I call Raycastcommand for all cars, or for every car ?

In fixedUpdate I call RaycastCommand.ScheduleBatch just one time every frame for every car, that means 400 calls for 400 cars.

Ideally one RaycastCommand.ScheduleBatch per FixedUpdate. There’s some overhead/cost to creating and executing each batch, so the more you include in the batch the better.

I think I understand what you say. Maybe should I check the result of the job with all raycasts instead of call a job, check, call another job, check. In my case I have only one call when the first sensor find something. Right ?

JobHandle handle = RaycastCommand.ScheduleBatch(commands, results, 1, default(JobHandle));
OR
JobHandle handle = RaycastCommand.ScheduleBatch(commands, results, sensorsCount, default(JobHandle));

?

Yeah, that would generally be better. Schedule all of the raycasts into one batch, then evaluate them all afterwards.

In my game, my basic approach is to loop over all of the rigidbodies I need to raycast for, and create a RaycastCommand. I then execute them all in one batch. Then I loop through all of the Rigidbodies again, checking the results to see if I need to do something with that rigidbody.