Search Unity

RayCast performance problem

Discussion in 'Scripting' started by Zavalichi, Apr 16, 2019.

  1. Zavalichi

    Zavalichi

    Joined:
    Oct 13, 2018
    Posts:
    162
    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:
    upload_2019-4-17_0-18-36.png

    Code (CSharp):
    1.  private void prioritySensors()
    2.     {
    3.         if (_currentWayPoint == null)
    4.             return;
    5.         if (Intersection)
    6.             _intersectionAhead = false;
    7.  
    8.         _reverse = false;
    9.         CarAhead = "";
    10.         _priority = false;
    11.         _isCarAhead = false;
    12.  
    13.         FrontCenterSensorPriority = false;
    14.         FrontLeftSensorPriority = false;
    15.         FrontObliqueLeftSensorPriority = false;
    16.         FrontRightSensorPriority = false;
    17.         FrontObliqueRightSensorPriority = false;
    18.         LeftSideSensorPriority = false;
    19.         RightSideSeonsorPriority = false;
    20.         BackLeftSensorPriority = false;
    21.         BackRightSensorPriority = false;
    22.  
    23.         // dimensiunea senzorului va fi adaptata in functie de viteza
    24.         float newFrontSensorsLength = 0;
    25.         // speed 15 -------------- FrontSL
    26.         // speed x  -------------- newFrontSL
    27.         if (CurrentSpeed > 100)
    28.             newFrontSensorsLength = 40;
    29.         else if (CurrentSpeed > 80)
    30.             newFrontSensorsLength = 35;
    31.         else if (CurrentSpeed > 60)
    32.             newFrontSensorsLength = 30;
    33.         else if (CurrentSpeed > 40)
    34.             newFrontSensorsLength = 25;
    35.         else if (CurrentSpeed > 30)
    36.             newFrontSensorsLength = 20;
    37.         else if (CurrentSpeed > 20)
    38.             newFrontSensorsLength = 15;
    39.         else if (CurrentSpeed > 15)
    40.             newFrontSensorsLength = 10;
    41.         else
    42.             newFrontSensorsLength = 3;
    43.         if (Intersection)
    44.             newFrontSensorsLength += 2;
    45.  
    46.         // Stabilim dimensiunea senzorilor in intersectii
    47.         float newFronSideSensorsLength = FrontSideSensorsLength;
    48.         float newFrontObliqSensorsAngle = FrontObliqSensorsAngle;
    49.         if (RoundAbout)
    50.             newFronSideSensorsLength *= 1.5f;
    51.         else if (Intersection && !GoRight)
    52.         {
    53.             newFronSideSensorsLength = 12;
    54.             if (GoForward)
    55.             {
    56.                 newFronSideSensorsLength = 8;
    57.                 newFrontObliqSensorsAngle = 5;
    58.             }
    59.  
    60.         }
    61.         float dim = FrontSideSensorsLength;
    62.  
    63.         RaycastHit hit = new RaycastHit();
    64.         Color colorSensor = new Color();
    65.         colorSensor = Color.green;
    66.  
    67.         Vector3 frontSensorsStartPosition = transform.position;
    68.         frontSensorsStartPosition += transform.forward * FrontSensorsPosition.z; // are aceeasi directie ca si masina
    69.         frontSensorsStartPosition += transform.up * FrontSensorsPosition.y; // se afla la aceeasi inaltime indiferent de pozitia masinii
    70.  
    71.         Vector3 sideSensorsStartPosition = transform.position;
    72.         sideSensorsStartPosition += transform.forward * SideSensorsPosition.z; // are aceeasi directie ca si masina
    73.         sideSensorsStartPosition += transform.up * SideSensorsPosition.y; // se afla la aceeasi inaltime indiferent de pozitia masinii
    74.  
    75.         Vector3 backObliqSensorsStartPosition = transform.position;
    76.         backObliqSensorsStartPosition += transform.forward * (-1) * BackSensorsPosition.z; // are aceeasi directie ca si masina
    77.         backObliqSensorsStartPosition += transform.up * BackSensorsPosition.y; // se afla la aceeasi inaltime indiferent de pozitia masinii
    78.  
    79.         RaycastHit[] hits;
    80.         hits = Physics.RaycastAll(frontSensorsStartPosition, transform.forward, newFrontSensorsLength);
    81.         // Front Center
    82.         bool hited = false;
    83.         if (hits.Length > 0)
    84.         {
    85.             foreach (var h in hits)
    86.             {
    87.                 // reduc viteza in intersectii
    88.                 if (h.collider.gameObject.CompareTag("Intersection"))
    89.                 {
    90.                     _intersectionAhead = true;
    91.                     if (CurrentSpeed > 30)
    92.                     {
    93.                         _isCarAhead = true;
    94.                         return;
    95.                     }
    96.                 }
    97.                 if (h.collider.gameObject.CompareTag("Car"))
    98.                 {
    99.                     hit = h;
    100.                     hited = true;
    101.                     break;
    102.                 }
    103.             }
    104.             if (hited)
    105.             {
    106.                 FrontCenterSensorPriority = true;
    107.  
    108.                 //Debug.DrawLine(frontSensorsStartPosition, hit.point, colorSensor);
    109.                 CarAhead = hit.collider.gameObject.name;
    110.                 if (hit.collider.CompareTag("Player"))
    111.                 {
    112.                     _isCarAhead = true;
    113.                     return;
    114.                 }
    115.  
    116.                 _priority = getPriority(hit.collider.gameObject, hit);
    117.                 _isCarAhead = !_priority;
    118.                 return;
    119.             }
    120.  
    121.         }
    122.  
    123.         // Front Left
    124.         frontSensorsStartPosition -= transform.right * FrontObliqSensorsPosition;
    125.         dim = (Intersection && !GoRight) ? newFronSideSensorsLength : newFrontSensorsLength + 1;
    126.         if (Physics.Raycast(frontSensorsStartPosition, transform.forward, out hit, dim))
    127.         {
    128.             if (!hit.collider.CompareTag("WayPoint") && !hit.collider.CompareTag("NotForSensors") && !hit.collider.CompareTag("Intersection"))
    129.             {
    130.                 //Debug.Log("FL Dim: " + dim + " NewLength" + newFrontSensorsLength + " Inter: " + newFronSideSensorsLength);
    131.                 FrontLeftSensorPriority = true;
    132.  
    133.                 Debug.DrawLine(frontSensorsStartPosition, hit.point, colorSensor);
    134.                 CarAhead = hit.collider.gameObject.name;
    135.  
    136.                 if (hit.collider.CompareTag("Player"))
    137.                 {
    138.                     _isCarAhead = true;
    139.                     return;
    140.                 }
    141.  
    142.                 _priority = getPriority(hit.collider.gameObject, hit);
    143.                 _isCarAhead = !_priority;
    144.                 return;
    145.  
    146.             }
    147.         }
    148.  
    149.         // Oblique Left      
    150.         dim = (Intersection && !GoRight) ? newFronSideSensorsLength : FrontSideSensorsLength;
    151.         if (Physics.Raycast(frontSensorsStartPosition, Quaternion.AngleAxis(-newFrontObliqSensorsAngle, transform.up) * transform.forward, out hit, dim))
    152.         {
    153.             if (!hit.collider.CompareTag("WayPoint") && !hit.collider.CompareTag("NotForSensors") && !hit.collider.CompareTag("Intersection"))
    154.             {
    155.                 //Debug.Log("OL Dim: " + dim + " NewLength" + FrontSideSensorsLength + " Inter: " + newFronSideSensorsLength);
    156.                 FrontObliqueLeftSensorPriority = true;
    157.  
    158.                 Debug.DrawLine(frontSensorsStartPosition, hit.point, colorSensor);
    159.                 CarAhead = hit.collider.gameObject.name;
    160.  
    161.                 if (hit.collider.CompareTag("Player"))
    162.                 {
    163.                     _isCarAhead = true;
    164.                     return;
    165.                 }
    166.  
    167.                 _priority = getPriority(hit.collider.gameObject, hit);
    168.                 _isCarAhead = !_priority;
    169.                 return;
    170.  
    171.             }
    172.         }
    173.  
    174.         // Front Right
    175.         frontSensorsStartPosition += 2 * transform.right * FrontObliqSensorsPosition;
    176.         dim = (Intersection && !GoRight) ? newFronSideSensorsLength : newFrontSensorsLength + 1;
    177.         if (Physics.Raycast(frontSensorsStartPosition, transform.forward, out hit, dim))
    178.         {
    179.             if (!hit.collider.CompareTag("WayPoint") && !hit.collider.CompareTag("NotForSensors") && !hit.collider.CompareTag("Intersection"))
    180.             {
    181.                 //Debug.Log("FR Dim: " + dim + " NewLength" + newFrontSensorsLength + " Inter: "+ newFronSideSensorsLength);
    182.  
    183.                 FrontRightSensorPriority = true;
    184.  
    185.                 Debug.DrawLine(frontSensorsStartPosition, hit.point, colorSensor);
    186.                 CarAhead = hit.collider.gameObject.name;
    187.  
    188.                 if (hit.collider.CompareTag("Player"))
    189.                 {
    190.                     _isCarAhead = true;
    191.                     return;
    192.                 }
    193.  
    194.                 _priority = getPriority(hit.collider.gameObject, hit);
    195.                 _isCarAhead = !_priority;
    196.                 return;
    197.             }
    198.         }
    199.  
    200.         // Oblique Right    
    201.         dim = (Intersection && !GoRight) ? newFronSideSensorsLength : FrontSideSensorsLength;
    202.         if (Physics.Raycast(frontSensorsStartPosition, Quaternion.AngleAxis(FrontObliqSensorsAngle, transform.up) * transform.forward, out hit, dim))
    203.         {
    204.             if (!hit.collider.CompareTag("WayPoint") && !hit.collider.CompareTag("NotForSensors") && !hit.collider.CompareTag("Intersection"))
    205.             {
    206.                 //Debug.Log("OR Dim: " + dim + " NewLength" + FrontSideSensorsLength + " Inter: " + newFronSideSensorsLength);
    207.                 FrontObliqueRightSensorPriority = true;
    208.  
    209.                 Debug.DrawLine(frontSensorsStartPosition, hit.point, colorSensor);
    210.                 CarAhead = hit.collider.gameObject.name;
    211.  
    212.                 if (hit.collider.CompareTag("Player"))
    213.                 {
    214.                     _isCarAhead = true;
    215.                     return;
    216.  
    217.                 }
    218.                 _priority = getPriority(hit.collider.gameObject, hit);
    219.                 _isCarAhead = !_priority;
    220.                 return;
    221.             }
    222.         }
    223.  
    224.         // RIGHT SIDE
    225.         sideSensorsStartPosition += transform.right * SidePosition;
    226.         if (!Intersection && (Mathf.Abs(_targetSteerAngle) > 7) || (Mathf.Abs(_dirAngle) > 10 && (_distance < 2)))
    227.         {
    228.             if (Physics.Raycast(sideSensorsStartPosition, Quaternion.AngleAxis(90, transform.up) * transform.forward, out hit, SideSensorsLength))
    229.             {
    230.                 if (!hit.collider.CompareTag("WayPoint") && !hit.collider.CompareTag("NotForSensors") && !hit.collider.CompareTag("Intersection"))
    231.                 {
    232.                     RightSideSeonsorPriority = true;
    233.  
    234.                     Debug.DrawLine(sideSensorsStartPosition, hit.point, colorSensor);
    235.                     CarAhead = hit.collider.gameObject.name;
    236.  
    237.                     if (hit.collider.CompareTag("Player"))
    238.                     {
    239.                         _isCarAhead = true;
    240.                         return;
    241.                     }
    242.  
    243.                     _priority = getPriority(hit.collider.gameObject, hit);
    244.                     _isCarAhead = !_priority;
    245.                     return;
    246.                 }
    247.             }
    248.         }
    249.  
    250.  
    251.         // LEFT SIDE
    252.         sideSensorsStartPosition -= 2 * transform.right * SidePosition;
    253.         if (!Intersection && (Mathf.Abs(_targetSteerAngle) > 7 || (Mathf.Abs(_dirAngle) > 10 && (_distance < 2))))
    254.         {
    255.             if (Physics.Raycast(sideSensorsStartPosition, Quaternion.AngleAxis(-90, transform.up) * transform.forward, out hit, SideSensorsLength))
    256.             {
    257.                 if (!hit.collider.CompareTag("WayPoint") && !hit.collider.CompareTag("NotForSensors") && !hit.collider.CompareTag("Intersection"))
    258.                 {
    259.                     LeftSideSensorPriority = true;
    260.  
    261.                     Debug.DrawLine(sideSensorsStartPosition, hit.point, colorSensor);
    262.                     CarAhead = hit.collider.gameObject.name;
    263.  
    264.                     if (hit.collider.CompareTag("Player"))
    265.                     {
    266.                         _isCarAhead = true;
    267.                         return;
    268.                     }
    269.  
    270.                     _priority = getPriority(hit.collider.gameObject, hit);
    271.                     _isCarAhead = !_priority;
    272.                     return;
    273.                 }
    274.             }
    275.  
    276.         }
    277.  
    278.  
    279.         // RIGHT OBLIQUE BACK
    280.         if (GoRight && !Intersection && _distance < 3)
    281.         {
    282.             backObliqSensorsStartPosition += transform.right * BackObliqSensorsPosition;
    283.             // Acest senzor se activeaza atunci cand masina isi schimba banda
    284.             if (Physics.Raycast(backObliqSensorsStartPosition, Quaternion.AngleAxis(BackObliqSensorsAngle, transform.up) * transform.forward, out hit, BackObliqSensorsLength))
    285.             {
    286.                 //Debug.Log("RIGHT");
    287.                 if (!hit.collider.CompareTag("WayPoint") && !hit.collider.CompareTag("NotForSensors") && !hit.collider.CompareTag("Intersection"))
    288.                 {
    289.  
    290.                     BackRightSensorPriority = true;
    291.  
    292.                     Debug.DrawLine(backObliqSensorsStartPosition, hit.point, colorSensor);
    293.                     CarAhead = hit.collider.gameObject.name;
    294.  
    295.                     if (hit.collider.CompareTag("Player"))
    296.                     {
    297.                         _isCarAhead = true;
    298.                         return;
    299.                     }
    300.  
    301.                     _priority = getPriority(hit.collider.gameObject, hit);
    302.                     _isCarAhead = !_priority;
    303.                     return;
    304.                 }
    305.             }
    306.         }
    307.  
    308.         // LEFT OBLIQUE BACK
    309.         if (GoLeft && !Intersection && _distance < 3)
    310.         {
    311.             backObliqSensorsStartPosition -= 2 * transform.right * BackObliqSensorsPosition;
    312.             if (Physics.Raycast(backObliqSensorsStartPosition, Quaternion.AngleAxis(-BackObliqSensorsAngle, transform.up) * transform.forward, out hit, BackObliqSensorsLength))
    313.             {
    314.                 //Debug.Log("LEFT");
    315.                 if (!hit.collider.CompareTag("WayPoint") && !hit.collider.CompareTag("NotForSensors") && !hit.collider.CompareTag("Intersection"))
    316.                 {
    317.                     BackLeftSensorPriority = true;
    318.  
    319.                     Debug.DrawLine(backObliqSensorsStartPosition, hit.point, colorSensor);
    320.                     CarAhead = hit.collider.gameObject.name;
    321.  
    322.                     if (hit.collider.CompareTag("Player"))
    323.                     {
    324.                         _isCarAhead = true;
    325.                         return;
    326.                     }
    327.  
    328.                     _priority = getPriority(hit.collider.gameObject, hit);
    329.                     _isCarAhead = !_priority;
    330.                     return;
    331.                 }
    332.             }
    333.         }
    334.  
    335.     }
     
  2. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,196
    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.

    https://docs.unity3d.com/ScriptReference/RaycastCommand.html

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

    Zavalichi

    Joined:
    Oct 13, 2018
    Posts:
    162
    Thank you,
    For now i dont understand how to use it, but I will try.
     
  4. Zavalichi

    Zavalichi

    Joined:
    Oct 13, 2018
    Posts:
    162
    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.


    Code (CSharp):
    1.  var results = new NativeArray<RaycastHit>(1, Allocator.Temp);
    2.         var commands = new NativeArray<RaycastCommand>(1, Allocator.Temp);
    3.  
    4.  
    5.         Vector3 frontSensorsStartPosition = transform.position;
    6.         frontSensorsStartPosition += transform.forward * FrontSensorsPosition.z; // are aceeasi directie ca si masina
    7.         frontSensorsStartPosition += transform.up * FrontSensorsPosition.y; // se afla la aceeasi inaltime indiferent de pozitia masinii
    8.  
    9.         Vector3 sideSensorsStartPosition = transform.position;
    10.         sideSensorsStartPosition += transform.forward * SideSensorsPosition.z; // are aceeasi directie ca si masina
    11.         sideSensorsStartPosition += transform.up * SideSensorsPosition.y; // se afla la aceeasi inaltime indiferent de pozitia masinii
    12.  
    13.         Vector3 backObliqSensorsStartPosition = transform.position;
    14.         backObliqSensorsStartPosition += transform.forward * (-1) * BackSensorsPosition.z; // are aceeasi directie ca si masina
    15.         backObliqSensorsStartPosition += transform.up * BackSensorsPosition.y; // se afla la aceeasi inaltime indiferent de pozitia masinii
    16.  
    17.         commands[0] = new RaycastCommand(frontSensorsStartPosition, transform.forward);
    18.         // Schedule the batch of raycasts
    19.         JobHandle handle = RaycastCommand.ScheduleBatch(commands, results, 1, default(JobHandle));
    20.  
    21.         // Wait for the batch processing job to complete
    22.         handle.Complete();
    23.  
    24.         // Copy the result. If batchedHit.collider is null there was no hit
    25.         RaycastHit batchedHit = results[0];
    26.  
    27.         //RaycastHit[] hits;
    28.          //hits = Physics.RaycastAll(frontSensorsStartPosition, transform.forward, newFrontSensorsLength);
    29.         // Front Center
    30.         bool hited = false;
    31.         if (results.Length > 0)
    32.         {
    33.             foreach (var h in results)
    34.             {
    35.                 // reduc viteza in intersectii
    36.                 if (h.collider.gameObject.CompareTag("Intersection"))
    37.                 {
    38.                     _intersectionAhead = true;
    39.                     if (CurrentSpeed > 30)
    40.                     {
    41.                         _isCarAhead = true;
    42.                         return;
    43.                     }
    44.                 }
    45.                 if (h.collider.gameObject.CompareTag("Car"))
    46.                 {
    47.                     hit = h;
    48.                     hited = true;
    49.                     break;
    50.                 }
    51.             }
    52.             if (hited)
    53.             {
    54.                 FrontCenterSensorPriority = true;
    55.  
    56.                 //Debug.DrawLine(frontSensorsStartPosition, hit.point, colorSensor);
    57.                 CarAhead = hit.collider.gameObject.name;
    58.                 if (hit.collider.CompareTag("Player"))
    59.                 {
    60.                     _isCarAhead = true;
    61.                     return;
    62.                 }
    63.  
    64.                 _priority = getPriority(hit.collider.gameObject, hit);
    65.                 _isCarAhead = !_priority;
    66.                 return;
    67.             }
    68.  
    69.         }
    70.  
    71.         // Dispose the buffers
    72.         results.Dispose();
    73.         commands.Dispose();
     
  5. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,196
  6. Zavalichi

    Zavalichi

    Joined:
    Oct 13, 2018
    Posts:
    162
    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.
     
  7. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,196
    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.
     
  8. Zavalichi

    Zavalichi

    Joined:
    Oct 13, 2018
    Posts:
    162
    IS better now?

    Code (CSharp):
    1.   bool hited = false;
    2.  
    3.         #region Sensor - Front-Center
    4.         // Front Center
    5.         RaycastHit[] hits;
    6.         hits = Physics.RaycastAll(frontSensorsStartPosition, transform.forward, newFrontSensorsLength);
    7.         if (hits.Length > 0)
    8.         {
    9.             foreach (var h in hits)
    10.             {
    11.                 // reduc viteza in intersectii
    12.                 if (h.collider.gameObject.CompareTag("Intersection"))
    13.                 {
    14.                     _intersectionAhead = true;
    15.                     if (CurrentSpeed > 30)
    16.                     {
    17.                         _isCarAhead = true;
    18.                         return;
    19.                     }
    20.                 }
    21.                 if (h.collider.gameObject.CompareTag("Car"))
    22.                 {
    23.                     hit = h;
    24.                     hited = true;
    25.                     break;
    26.                 }
    27.             }
    28.             if (hited)
    29.             {
    30.                 FrontCenterSensorPriority = true;
    31.  
    32.                 Debug.DrawLine(frontSensorsStartPosition, hit.point, colorSensor);
    33.                 CarAhead = hit.collider.gameObject.name;
    34.                 if (hit.collider.CompareTag("Player"))
    35.                 {
    36.                     _isCarAhead = true;
    37.                     return;
    38.                 }
    39.  
    40.                 _priority = getPriority(hit.collider.gameObject, hit);
    41.                 _isCarAhead = !_priority;
    42.                 return;
    43.             }
    44.  
    45.         }
    46.         #endregion
    47.  
    48.         var results = new NativeArray<RaycastHit>(1, Allocator.Temp);
    49.         var commands = new NativeArray<RaycastCommand>(1, Allocator.Temp);
    50.  
    51.         #region Sensor - Front Left
    52.         if (!hited)
    53.         {
    54.             frontSensorsStartPosition -= transform.right * FrontObliqSensorsPosition;
    55.             dim = (Intersection && !GoRight) ? newFronSideSensorsLength : newFrontSensorsLength + 1;
    56.  
    57.             commands[0] = new RaycastCommand(frontSensorsStartPosition, transform.forward, dim);
    58.             JobHandle handle = RaycastCommand.ScheduleBatch(commands, results, 1, default(JobHandle));
    59.             handle.Complete();
    60.             RaycastHit batchedHit = results[0];
    61.  
    62.             if ((batchedHit.collider) && !batchedHit.collider.CompareTag("WayPoint") && !batchedHit.collider.CompareTag("NotForSensors") && !batchedHit.collider.CompareTag("Intersection"))
    63.             {
    64.                 hited = true;
    65.                 FrontLeftSensorPriority = true;
    66.  
    67.                 Debug.DrawLine(frontSensorsStartPosition, batchedHit.point, colorSensor);
    68.                 CarAhead = batchedHit.collider.gameObject.name;
    69.  
    70.                 if (batchedHit.collider.CompareTag("Player"))
    71.                     _isCarAhead = true;
    72.  
    73.                 else
    74.                 {
    75.                     _priority = getPriority(batchedHit.collider.gameObject, batchedHit);
    76.                     _isCarAhead = !_priority;
    77.                 }
    78.             }
    79.         }
    80.         #endregion
    81.  
    82.         #region Sensor - Front Left Oblique
    83.         if (!hited)
    84.         {
    85.             dim = (Intersection && !GoRight) ? newFronSideSensorsLength : FrontSideSensorsLength;
    86.  
    87.             commands[0] = new RaycastCommand(frontSensorsStartPosition, Quaternion.AngleAxis(-newFrontObliqSensorsAngle, transform.up) * transform.forward, dim);
    88.             JobHandle handle = RaycastCommand.ScheduleBatch(commands, results, 1, default(JobHandle));
    89.             handle.Complete();
    90.             RaycastHit batchedHit = results[0];
    91.  
    92.             if ((batchedHit.collider) && (batchedHit.collider) && !batchedHit.collider.CompareTag("WayPoint") && !batchedHit.collider.CompareTag("NotForSensors") && !batchedHit.collider.CompareTag("Intersection"))
    93.             {
    94.                 hited = true;
    95.                 FrontObliqueLeftSensorPriority = true;
    96.  
    97.                 Debug.DrawLine(frontSensorsStartPosition, batchedHit.point, colorSensor);
    98.                 CarAhead = batchedHit.collider.gameObject.name;
    99.  
    100.                 if (batchedHit.collider.CompareTag("Player"))
    101.                     _isCarAhead = true;
    102.                 else
    103.                 {
    104.                     _priority = getPriority(batchedHit.collider.gameObject, batchedHit);
    105.                     _isCarAhead = !_priority;
    106.                 }
    107.             }
    108.         }
    109.         #endregion
    110.  
    111.         #region Sensor - Front Right
    112.         if (!hited)
    113.         {
    114.             frontSensorsStartPosition += 2 * transform.right * FrontObliqSensorsPosition;
    115.             dim = (Intersection && !GoRight) ? newFronSideSensorsLength : newFrontSensorsLength + 1;
    116.  
    117.             commands[0] = new RaycastCommand(frontSensorsStartPosition, transform.forward, dim);
    118.             JobHandle handle = RaycastCommand.ScheduleBatch(commands, results, 1, default(JobHandle));
    119.             handle.Complete();
    120.             RaycastHit batchedHit = results[0];
    121.  
    122.             if ((batchedHit.collider) && !batchedHit.collider.CompareTag("WayPoint") && !batchedHit.collider.CompareTag("NotForSensors") && !batchedHit.collider.CompareTag("Intersection"))
    123.             {
    124.                 hited = true;
    125.                 FrontRightSensorPriority = true;
    126.  
    127.                 Debug.DrawLine(frontSensorsStartPosition, batchedHit.point, colorSensor);
    128.                 CarAhead = batchedHit.collider.gameObject.name;
    129.  
    130.                 if (batchedHit.collider.CompareTag("Player"))
    131.                     _isCarAhead = true;
    132.                 else
    133.                 {
    134.                     _priority = getPriority(batchedHit.collider.gameObject, batchedHit);
    135.                     _isCarAhead = !_priority;
    136.                 }
    137.             }
    138.         }
    139.         #endregion
    140.  
    141.         #region Sensor - Front Right Oblique
    142.         if (!hited)
    143.         {
    144.             dim = (Intersection && !GoRight) ? newFronSideSensorsLength : FrontSideSensorsLength;
    145.  
    146.             commands[0] = new RaycastCommand(frontSensorsStartPosition, Quaternion.AngleAxis(FrontObliqSensorsAngle, transform.up) * transform.forward, dim);
    147.             JobHandle handle = RaycastCommand.ScheduleBatch(commands, results, 1, default(JobHandle));
    148.             handle.Complete();
    149.             RaycastHit batchedHit = results[0];
    150.  
    151.             if ((batchedHit.collider) && !batchedHit.collider.CompareTag("WayPoint") && !batchedHit.collider.CompareTag("NotForSensors") && !batchedHit.collider.CompareTag("Intersection"))
    152.             {
    153.                 hited = true;
    154.                 FrontObliqueRightSensorPriority = true;
    155.  
    156.                 Debug.DrawLine(frontSensorsStartPosition, batchedHit.point, colorSensor);
    157.                 CarAhead = batchedHit.collider.gameObject.name;
    158.  
    159.                 if (batchedHit.collider.CompareTag("Player"))
    160.                     _isCarAhead = true;
    161.                 else
    162.                 {
    163.                     _priority = getPriority(batchedHit.collider.gameObject, batchedHit);
    164.                     _isCarAhead = !_priority;
    165.                 }
    166.             }
    167.         }
    168.         #endregion
    169.  
    170.         #region Sensor - Side Left
    171.         if (!Intersection && (Mathf.Abs(_targetSteerAngle) > 7 || (Mathf.Abs(_dirAngle) > 10 && (_distance < 2))))
    172.         {
    173.             if (!hited)
    174.             {
    175.                 sideSensorsStartPosition -= transform.right * SidePosition;
    176.  
    177.                 commands[0] = new RaycastCommand(sideSensorsStartPosition, Quaternion.AngleAxis(-90, transform.up) * transform.forward, SideSensorsLength);
    178.                 JobHandle handle = RaycastCommand.ScheduleBatch(commands, results, 1, default(JobHandle));
    179.                 handle.Complete();
    180.                 RaycastHit batchedHit = results[0];
    181.  
    182.                 if ((batchedHit.collider) && !batchedHit.collider.CompareTag("WayPoint") && !batchedHit.collider.CompareTag("NotForSensors") && !batchedHit.collider.CompareTag("Intersection"))
    183.                 {
    184.                     hited = true;
    185.                     LeftSideSensorPriority = true;
    186.  
    187.                     Debug.DrawLine(sideSensorsStartPosition, batchedHit.point, colorSensor);
    188.                     CarAhead = batchedHit.collider.gameObject.name;
    189.  
    190.                     if (batchedHit.collider.CompareTag("Player"))
    191.                         _isCarAhead = true;
    192.                     else
    193.                     {
    194.                         _priority = getPriority(batchedHit.collider.gameObject, batchedHit);
    195.                         _isCarAhead = !_priority;
    196.                     }
    197.                 }
    198.             }
    199.  
    200.         }
    201.         #endregion
    202.  
    203.         #region Sensor - Side Right
    204.         if (!Intersection && (Mathf.Abs(_targetSteerAngle) > 7) || (Mathf.Abs(_dirAngle) > 10 && (_distance < 2)))
    205.         {
    206.             if (!hited)
    207.             {
    208.                 sideSensorsStartPosition += 2 * transform.right * SidePosition;
    209.  
    210.                 commands[0] = new RaycastCommand(sideSensorsStartPosition, Quaternion.AngleAxis(90, transform.up) * transform.forward, SideSensorsLength);
    211.                 JobHandle handle = RaycastCommand.ScheduleBatch(commands, results, 1, default(JobHandle));
    212.                 handle.Complete();
    213.                 RaycastHit batchedHit = results[0];
    214.  
    215.                 if ( (batchedHit.collider) && !batchedHit.collider.CompareTag("WayPoint") && !batchedHit.collider.CompareTag("NotForSensors") && !batchedHit.collider.CompareTag("Intersection"))
    216.                 {
    217.                     hited = true;
    218.                     RightSideSeonsorPriority = true;
    219.  
    220.                     Debug.DrawLine(sideSensorsStartPosition, batchedHit.point, colorSensor);
    221.                     CarAhead = batchedHit.collider.gameObject.name;
    222.  
    223.                     if (batchedHit.collider.CompareTag("Player"))
    224.                         _isCarAhead = true;
    225.                     else
    226.                     {
    227.                         _priority = getPriority(batchedHit.collider.gameObject, batchedHit);
    228.                         _isCarAhead = !_priority;
    229.                     }
    230.                 }
    231.             }
    232.         }
    233.         #endregion
    234.  
    235.         #region Sensor - Back Left Oblique
    236.         if (GoLeft && !Intersection && _distance < 3)
    237.         {
    238.             backObliqSensorsStartPosition -= 2 * transform.right * BackObliqSensorsPosition;
    239.             if (!hited)
    240.             {
    241.  
    242.                 commands[0] = new RaycastCommand(backObliqSensorsStartPosition, Quaternion.AngleAxis(-BackObliqSensorsAngle, transform.up) * transform.forward, BackObliqSensorsLength);
    243.                 JobHandle handle = RaycastCommand.ScheduleBatch(commands, results, 1, default(JobHandle));
    244.                 handle.Complete();
    245.                 RaycastHit batchedHit = results[0];
    246.  
    247.                 if ((batchedHit.collider) && !batchedHit.collider.CompareTag("WayPoint") && !batchedHit.collider.CompareTag("NotForSensors") && !batchedHit.collider.CompareTag("Intersection"))
    248.                 {
    249.                     hited = true;
    250.                     BackLeftSensorPriority = true;
    251.  
    252.                     Debug.DrawLine(backObliqSensorsStartPosition, batchedHit.point, colorSensor);
    253.                     CarAhead = batchedHit.collider.gameObject.name;
    254.  
    255.                     if (batchedHit.collider.CompareTag("Player"))
    256.                         _isCarAhead = true;
    257.                     else
    258.                     {
    259.                         _priority = getPriority(batchedHit.collider.gameObject, batchedHit);
    260.                         _isCarAhead = !_priority;
    261.                     }
    262.                 }
    263.             }
    264.         }
    265.         #endregion
    266.  
    267.         #region Sensor - Back Right Oblique
    268.         if (GoRight && !Intersection && _distance < 3)
    269.         {
    270.             if (!hited)
    271.             {
    272.                 backObliqSensorsStartPosition += transform.right * BackObliqSensorsPosition;
    273.  
    274.                 commands[0] = new RaycastCommand(backObliqSensorsStartPosition, Quaternion.AngleAxis(BackObliqSensorsAngle, transform.up) * transform.forward, BackObliqSensorsLength);
    275.                 JobHandle handle = RaycastCommand.ScheduleBatch(commands, results, 1, default(JobHandle));
    276.                 handle.Complete();
    277.                 RaycastHit batchedHit = results[0];
    278.  
    279.                 if ((batchedHit.collider) && !batchedHit.collider.CompareTag("WayPoint") && !batchedHit.collider.CompareTag("NotForSensors") && !batchedHit.collider.CompareTag("Intersection"))
    280.                 {
    281.                     hited = true;
    282.                     BackRightSensorPriority = true;
    283.  
    284.                     Debug.DrawLine(backObliqSensorsStartPosition, batchedHit.point, colorSensor);
    285.                     CarAhead = batchedHit.collider.gameObject.name;
    286.  
    287.                     if (batchedHit.collider.CompareTag("Player"))
    288.                         _isCarAhead = true;
    289.                     else
    290.                     {
    291.                         _priority = getPriority(batchedHit.collider.gameObject, batchedHit);
    292.                         _isCarAhead = !_priority;
    293.                     }
    294.                 }
    295.             }
    296.         }
    297.         #endregion
    298.  
    299.         // Dispose the buffers
    300.         results.Dispose();
    301.         commands.Dispose();
     
  9. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,196
    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.
     
  10. Zavalichi

    Zavalichi

    Joined:
    Oct 13, 2018
    Posts:
    162
    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.
     
  11. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,196
    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.
     
  12. Zavalichi

    Zavalichi

    Joined:
    Oct 13, 2018
    Posts:
    162
    And call the raycastCommand at every frame? Sound interesting
     
  13. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,196
    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.
     
  14. Zavalichi

    Zavalichi

    Joined:
    Oct 13, 2018
    Posts:
    162
    I think now is worst,

    upload_2019-4-17_20-21-54.png
     
  15. Zavalichi

    Zavalichi

    Joined:
    Oct 13, 2018
    Posts:
    162
    With deep profiler upload_2019-4-17_20-23-58.png
     
  16. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,196
    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.
     
  17. Zavalichi

    Zavalichi

    Joined:
    Oct 13, 2018
    Posts:
    162
    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.
     
  18. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,196
    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.
     
  19. Zavalichi

    Zavalichi

    Joined:
    Oct 13, 2018
    Posts:
    162
    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));

    ?
     
    Last edited: Apr 17, 2019
  20. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,196
    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.
     
  21. Zavalichi

    Zavalichi

    Joined:
    Oct 13, 2018
    Posts:
    162
    I don't think I can use this for cars, because every car has his own brain.
    I did this, is better?

    value 1 is good for this? JobHandle handle = RaycastCommand.ScheduleBatch(commands, results, 1, default(JobHandle));

    Code (CSharp):
    1. int sensorsCount = 10;
    2.  
    3.         var results = new NativeArray<RaycastHit>(sensorsCount, Allocator.Temp);
    4.         var commands = new NativeArray<RaycastCommand>(sensorsCount, Allocator.Temp);
    5.  
    6.         // Sensor - Front-Center
    7.         int carsLayerMask = 1 << 10;
    8.         int intersectionsLAyerMask = 1 << 11;
    9.         commands[0] = new RaycastCommand(frontSensorsStartPosition, transform.forward, newFrontSensorsLength, carsLayerMask); //cars
    10.         commands[1] = new RaycastCommand(frontSensorsStartPosition, transform.forward, newFrontSensorsLength, intersectionsLAyerMask); // intersections
    11.  
    12.         //Sensor - Front Left
    13.         frontSensorsStartPosition -= transform.right * FrontObliqSensorsPosition;
    14.         dim = (Intersection && !GoRight) ? newFronSideSensorsLength : newFrontSensorsLength + 1;
    15.         commands[2] = new RaycastCommand(frontSensorsStartPosition, transform.forward, dim);
    16.  
    17.         //Sensor - Front Left Oblique
    18.         dim = (Intersection && !GoRight) ? newFronSideSensorsLength : FrontSideSensorsLength;
    19.         commands[3] = new RaycastCommand(frontSensorsStartPosition, Quaternion.AngleAxis(-newFrontObliqSensorsAngle, transform.up) * transform.forward, dim);
    20.  
    21.         //Sensor - Front Right
    22.         frontSensorsStartPosition += 2 * transform.right * FrontObliqSensorsPosition;
    23.         dim = (Intersection && !GoRight) ? newFronSideSensorsLength : newFrontSensorsLength + 1;
    24.         commands[4] = new RaycastCommand(frontSensorsStartPosition, transform.forward, dim);
    25.  
    26.         //Sensor - Front Right Oblique
    27.         dim = (Intersection && !GoRight) ? newFronSideSensorsLength : FrontSideSensorsLength;
    28.         commands[5] = new RaycastCommand(frontSensorsStartPosition, Quaternion.AngleAxis(FrontObliqSensorsAngle, transform.up) * transform.forward, dim);
    29.  
    30.         //Sensor - Side Left
    31.         sideSensorsStartPosition -= transform.right * SidePosition;
    32.         commands[6] = new RaycastCommand(sideSensorsStartPosition, Quaternion.AngleAxis(-90, transform.up) * transform.forward, SideSensorsLength);
    33.  
    34.         //Sensor - Side Right
    35.         sideSensorsStartPosition += 2 * transform.right * SidePosition;
    36.         commands[7] = new RaycastCommand(sideSensorsStartPosition, Quaternion.AngleAxis(90, transform.up) * transform.forward, SideSensorsLength);
    37.  
    38.         //Sensor - Back Left Oblique
    39.         commands[8] = new RaycastCommand(backObliqSensorsStartPosition, Quaternion.AngleAxis(-BackObliqSensorsAngle, transform.up) * transform.forward, BackObliqSensorsLength);
    40.  
    41.         //Sensor - Back Right Oblique
    42.         backObliqSensorsStartPosition += transform.right * BackObliqSensorsPosition;
    43.         commands[9] = new RaycastCommand(backObliqSensorsStartPosition, Quaternion.AngleAxis(BackObliqSensorsAngle, transform.up) * transform.forward, BackObliqSensorsLength);
    44.  
    45.  
    46.         JobHandle handle = RaycastCommand.ScheduleBatch(commands, results, 1, default(JobHandle));
    47.         handle.Complete();
    48.  
    49.         for (int i = 0; i < results.Length; ++i)
    50.         {
    51.             if (results[i].collider != null)
    52.             {
    53.                 switch (i)
    54.                 {
    55.                     case 0:// Sensor - Front-Center (for cars)
    56.                         checkFrontCenterSensor(results[i], frontSensorsStartPosition);
    57.                         break;
    58.                     case 1:// Sensor - Front-Center (for intersection)
    59.                         checkFrontCenterSensor(results[i], frontSensorsStartPosition);
    60.                         break;
    61.                     case 2://Sensor - Front Left
    62.                         checkFrontLeftSensor(results[i], frontSensorsStartPosition);
    63.                         break;
    64.                     case 3://Sensor - Front Left Oblique
    65.                         checkFrontLeftObliqueSensor(results[i], frontSensorsStartPosition);
    66.                         break;
    67.                     case 4://Sensor - Front Right
    68.                         checkFrontRightSensor(results[i], frontSensorsStartPosition);
    69.                         break;
    70.                     case 5://Sensor - Front Right Oblique
    71.                         checkFrontRightObliqueSensor(results[i], frontSensorsStartPosition);
    72.                         break;
    73.                     case 6://Sensor - Side Left
    74.                         checkSideLeftSensor(results[i], sideSensorsStartPosition);
    75.                         break;
    76.                     case 7://Sensor - Side Right
    77.                         checkSideRightSensor(results[i], sideSensorsStartPosition);
    78.                         break;
    79.                     case 8: //Sensor - Back Left Oblique
    80.                         checkBackLeftObliquetSensor(results[i], backObliqSensorsStartPosition);
    81.                         break;
    82.                     case 9://Sensor - Back Right Oblique
    83.                         checkBackRightObliquetSensor(results[i], backObliqSensorsStartPosition);
    84.                         break;
    85.                     default:
    86.                         break;
    87.                 }
    88.             }
    89.         }
    90.         // Dispose the buffers
    91.         results.Dispose();
    92.         commands.Dispose();
     
  22. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,196
    Probably better than you had it before, but I'm really not sure how many raycasts you need to include in a batch before it starts being more efficient than doing individual raycasts. Maybe it's faster, but it's entirely possible that you won't see real gains unless you get the batch count down.
     
  23. Zavalichi

    Zavalichi

    Joined:
    Oct 13, 2018
    Posts:
    162
    * And about this> JobHandle handle = RaycastCommand.ScheduleBatch(commands, results, 1, default(JobHandle)); ? Value 1 is good ?

    *What do you mean: Maybe it's faster, but it's entirely possible that you won't see real gains unless you get the batch count down. ?
     
  24. Zavalichi

    Zavalichi

    Joined:
    Oct 13, 2018
    Posts:
    162
    I have a better performance for raycastcommand, but NativeArray looks not good...
    upload_2019-4-17_21-36-43.png