Search Unity

Question I got issue with raycast performance, for many thousands of rays.

Discussion in 'Physics for ECS' started by Antypodish, Feb 21, 2021.

  1. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,779
    Does got anyone has some ideas, how to improve this system?
    Specially around the part of the raycast.
    I suspect that the job seems to be called multiple times, because of FixedStepSimulationSystemGroup.

    Code (CSharp):
    1. using UnityEngine ;
    2.  
    3. using Unity.Jobs ;
    4. using Unity.Physics ;
    5. using Unity.Physics.Systems ;
    6. using Unity.Physics.Extensions ;
    7. using Unity.Entities ;
    8. using Unity.Collections ;
    9. using Unity.Transforms ;
    10. using Unity.Mathematics ;
    11.  
    12. using Antypodish.DOTS ;
    13. using Antypodish.GeneticNueralNetwork.DOTS ;
    14.  
    15.  
    16. namespace Antypodish.AI.DOTS
    17. {
    18.  
    19.     [UpdateInGroup ( typeof ( FixedStepSimulationSystemGroup ))]
    20.     [UpdateAfter ( typeof ( EndFramePhysicsSystem ))]
    21.     public class LIDARSystem : SystemBase
    22.     {
    23.  
    24.         BuildPhysicsWorld  buildPhysicsWorld ;
    25.         EndFramePhysicsSystem endFramePhysicsSystem;
    26.      
    27.         int i_raysCount = 9 ;
    28.         quaternion q_90deg ;
    29.         NativeArray <quaternion> na_rays ;
    30.  
    31.         protected override void OnCreate ( )
    32.         {
    33.             buildPhysicsWorld = World.GetOrCreateSystem <BuildPhysicsWorld> () ;
    34.             endFramePhysicsSystem   = World.GetExistingSystem <EndFramePhysicsSystem> () ;
    35.  
    36.             base.OnCreate ( );
    37.         }
    38.  
    39.         protected override void OnStartRunning ( )
    40.         {
    41.  
    42.             // LIDAR rays 180 degree, from left to front to right.
    43.             q_90deg  = quaternion.RotateY ( ( math.PI * 0.5f ) ) ;
    44.             na_rays  = new NativeArray<quaternion> ( i_raysCount, Allocator.Persistent ) ;
    45.          
    46.             float f_rayPiFraction = math.PI / ( i_raysCount - 1 ) ;
    47.  
    48.             for ( int i = 0; i < i_raysCount; i ++ )
    49.             {
    50.                 na_rays [i] = math.mul ( quaternion.RotateY ( ( f_rayPiFraction * i ) ), q_90deg ) ;
    51.             }
    52.         }
    53.  
    54.         protected override void OnStopRunning ( )
    55.         {
    56.             na_rays.Dispose () ;
    57.         }
    58.  
    59.         protected override void OnUpdate ( )
    60.         {
    61.  
    62.             CollisionWorld collisionWorld = buildPhysicsWorld.PhysicsWorld.CollisionWorld ;
    63.             Dependency                    = JobHandle.CombineDependencies ( Dependency, endFramePhysicsSystem.GetOutputDependency ()) ;
    64.          
    65.             var na_rays                   = this.na_rays ;
    66.             int i_raysCount               = this.i_raysCount ;
    67.  
    68.  
    69.             Entities
    70.                 .WithName ( "LIDARJob" )
    71.                 .WithAll <NNBrainTag, LIDARTag, IsAliveTag> ()
    72.                 .WithNone <NNIsFinishedTag> ()
    73.                 .WithReadOnly ( collisionWorld )
    74.                 // .WithReadOnly ( collector )
    75.                 .WithReadOnly ( na_rays )
    76.                 .ForEach ( ( ref DynamicBuffer <NNInputNeuronsValuesBuffer> a_inputLayerValues, in Translation position, in Rotation q, in VehicleVelocityComponent velocity ) =>
    77.             {
    78.  
    79.                 float3 f3_startPoint = position.Value ;
    80.  
    81.  
    82.                 for ( int i = 0; i < i_raysCount; i ++ )
    83.                 {
    84.                  
    85.                     quaternion q_rayDirection = na_rays [i] ;
    86.  
    87.                     float3 f3_endPoint        = f3_startPoint + math.mul ( math.mul ( q.Value, q_rayDirection ), Vector3.forward ) * 3 ;
    88.                  
    89.                     var raycastInput = new RaycastInput
    90.                     {
    91.                         Start  = f3_startPoint,
    92.                         End    = f3_endPoint,
    93.                         Filter = CollisionFilter.Default
    94.                     } ;
    95.                  
    96.                     // raycastInput.Filter.CollidesWith = 2 ; // Scores layer.
    97.                     raycastInput.Filter.CollidesWith = 1 ; // Barriers layer.
    98.  
    99.                     float f_input = -1 ;
    100.                  
    101.                     var collector = new IgnoreTransparentClosestHitCollector ( collisionWorld ) ;
    102.  
    103.                     if ( collisionWorld.CastRay ( raycastInput, ref collector ) )
    104.                     {
    105.                         Unity.Physics.RaycastHit hit = collector.ClosestHit ;
    106.  
    107. // Debug.DrawLine ( f3_startPoint, f3_endPoint, Color.red ) ;
    108. // Debug.DrawLine ( f3_startPoint, hit.Position, Color.green ) ; // Length of ray, until hit collider.
    109.  
    110.                         f_input = math.lengthsq ( hit.Position - f3_startPoint ) ;
    111.                     }
    112.                     // else
    113.                     // {
    114. // Debug.DrawLine ( f3_startPoint, f3_endPoint, Color.blue ) ;
    115.                     // }
    116.                  
    117.                     a_inputLayerValues [i] = new NNInputNeuronsValuesBuffer () { f = f_input } ;
    118.  
    119.                 }
    120.  
    121.                 a_inputLayerValues [a_inputLayerValues.Length -1] = new NNInputNeuronsValuesBuffer () { f = math.length ( velocity.f_forwardSpeed ) } ;
    122.                 a_inputLayerValues [a_inputLayerValues.Length -2] = new NNInputNeuronsValuesBuffer () { f = math.length ( velocity.f_sideWaySkiddSpeed ) } ;
    123.  
    124.             }).ScheduleParallel ();
    125.  
    126.         }
    127.     }
    128. }

    Edit:

    If I replace
    Code (CSharp):
    1. [UpdateInGroup ( typeof ( FixedStepSimulationSystemGroup ))]
    with
    Code (CSharp):
    1. [UpdateAfter ( typeof ( FixedStepSimulationSystemGroup ))]
    Things got much better.
    But is it wise?
    Appears to work.
     
    Last edited: Feb 21, 2021
  2. petarmHavok

    petarmHavok

    Joined:
    Nov 20, 2018
    Posts:
    461
    Yeah, it would be faster, but the question is if it's correct - you have been running one job per physics step, and now you are running one job per rendering step. It all boils down to what exactly you want to achieve.

    On a side note, you probably need to call buildPhysicsWorld.AddInputDependencyToComplete(Dependency) at the end of your OnUpdate() to make sure BuildPhysicsWorld doesn't reset your PhysicsWorld before query is done.
     
    Antypodish likes this.