Search Unity

Raycast for 20000 entities using Entities.ForEach

Discussion in 'Entity Component System' started by Michelle_Ca, Apr 25, 2020.

  1. Michelle_Ca

    Michelle_Ca

    Joined:
    Aug 19, 2019
    Posts:
    113
    Please i need help I spent a week searching and found nothing useful !
    how can i create Raycast for 20000 entities with best performance
    I just need that Raycast to get Surface normals under the entities and align the entity to this normal
    i'm looking for an example or any tutorial on how to raycasting from entities using Entities.ForEach
    thank you !
     
    GDevTeam likes this.
  2. JakHussain

    JakHussain

    Joined:
    Oct 20, 2016
    Posts:
    318
    Michelle_Ca likes this.
  3. Michelle_Ca

    Michelle_Ca

    Joined:
    Aug 19, 2019
    Posts:
    113
    thank you JakHussain !

    I tried this code in JobComponentSystem since I want to take advantage of Burst Compiler but give me 2 errors :oops:
    this is the code :

    Code (CSharp):
    1. using Unity.Entities;
    2. using Unity.Jobs;
    3. using Unity.Physics;
    4. using Unity.Collections;
    5. using Unity.Physics.Systems;
    6. using Unity.Transforms;
    7. using Unity.Mathematics;
    8.  
    9.  
    10. public class GameMangerDotstest : JobComponentSystem
    11. {
    12.  
    13.     protected override JobHandle OnUpdate(JobHandle inputDeps)
    14.     {
    15.         float DeltaTime = Time.DeltaTime;
    16.         var physicsWorldSystem = World.DefaultGameObjectInjectionWorld.GetExistingSystem<BuildPhysicsWorld>();
    17.          var collisionWorld = physicsWorldSystem.PhysicsWorld.CollisionWorld;
    18.  
    19.         JobHandle jobhandle = Entities.WithAll<BoxTag>().ForEach((ref Translation translation, ref LocalToWorld localtoworld, ref Rotation rotation, ref PhysicsVelocity velocity) => {
    20.  
    21.             float3 RayFrom = localtoworld.Value.c3.xyz;
    22.             float3 RayTo = RayFrom - (10 * localtoworld.Value.c1.xyz);
    23.  
    24.             RaycastInput input = new RaycastInput()
    25.             {
    26.  
    27.                 Start = RayFrom,
    28.                 End = RayTo,
    29.  
    30.                 Filter = new CollisionFilter
    31.                 {
    32.                     BelongsTo = ~0u,
    33.                     CollidesWith = ~0u,
    34.                     GroupIndex = 0
    35.                 }
    36.             };
    37.  
    38.             Unity.Physics.RaycastHit hit = new Unity.Physics.RaycastHit();
    39.             bool haveHit = collisionWorld.CastRay(input, out hit);
    40.  
    41.             if (haveHit)
    42.             {
    43.                
    44.                 translation.Value += 1f * localtoworld.Value.c2.xyz;
    45.             }
    46.             else
    47.             {
    48.  
    49.             }
    50.         }).Schedule(inputDeps);
    51.  
    52.  
    53.         return jobhandle;
    54.  
    55.     }
    56. }
    the BoxTag is just empty IComponentData attached to a cube




    when i start i got this 2 errors :

    InvalidOperationException: The previously scheduled job Broadphase:prepareStaticBodyDataJob writes to the NativeArray PrepareStaticBodyDataJob.FiltersOut. You are trying to schedule a new job GameMangerDots:<>c__DisplayClass_OnUpdate_LambdaJob0, which reads from the same NativeArray (via <>c__DisplayClass_OnUpdate_LambdaJob0.Data.collisionWorldRo.collisionWorld.Broadphase.m_StaticTree.BodyFilters). To guarantee safety, you must include Broadphase:prepareStaticBodyDataJob as a dependency of the newly scheduled job.
    Unity.Entities.JobChunkExtensions.ScheduleInternal[T] (T& jobData, Unity.Entities.EntityQuery query, Unity.Jobs.JobHandle dependsOn, Unity.Jobs.LowLevel.Unsafe.ScheduleMode mode, System.Boolean isParallel) (at Library/PackageCache/com.unity.entities@0.6.0-preview.24/Unity.Entities/IJobChunk.cs:216)
    Unity.Entities.JobChunkExtensions.ScheduleParallel[T] (T jobData, Unity.Entities.EntityQuery query, Unity.Jobs.JobHandle dependsOn) (at Library/PackageCache/com.unity.entities@0.6.0-preview.24/Unity.Entities/IJobChunk.cs:122)
    GameMangerDots.OnUpdate (Unity.Jobs.JobHandle inputDeps) (at Assets/Dots Scripts/GameMangerDots.cs:36)
    Unity.Entities.JobComponentSystem.Update () (at Library/PackageCache/com.unity.entities@0.6.0-preview.24/Unity.Entities/JobComponentSystem.cs:129)
    Unity.Entities.ComponentSystemGroup.UpdateAllSystems () (at Library/PackageCache/com.unity.entities@0.6.0-preview.24/Unity.Entities/ComponentSystemGroup.cs:182)
    UnityEngine.Debug:LogException(Exception)
    Unity.Debug:LogException(Exception) (at Library/PackageCache/com.unity.entities@0.6.0-preview.24/Unity.Entities/Stubs/Unity/Debug.cs:19)
    Unity.Entities.ComponentSystemGroup:UpdateAllSystems() (at Library/PackageCache/com.unity.entities@0.6.0-preview.24/Unity.Entities/ComponentSystemGroup.cs:186)
    Unity.Entities.ComponentSystemGroup:OnUpdate() (at Library/PackageCache/com.unity.entities@0.6.0-preview.24/Unity.Entities/ComponentSystemGroup.cs:169)
    Unity.Entities.ComponentSystem:Update() (at Library/PackageCache/com.unity.entities@0.6.0-preview.24/Unity.Entities/ComponentSystem.cs:107)
    Unity.Entities.DummyDelegateWrapper:TriggerUpdate() (at Library/PackageCache/com.unity.entities@0.6.0-preview.24/Unity.Entities/ScriptBehaviourUpdateOrder.cs:152)



    and this :

    A Native Collection has not been disposed, resulting in a memory leak. Enable Full StackTraces to get more details.
     
  4. desertGhost_

    desertGhost_

    Joined:
    Apr 12, 2018
    Posts:
    260
    Unity Physics requires you to order your system dependencies in a certain way.

    Try this:

    Code (CSharp):
    1. using Unity.Entities;
    2. using Unity.Jobs;
    3. using Unity.Physics;
    4. using Unity.Collections;
    5. using Unity.Physics.Systems;
    6. using Unity.Transforms;
    7. using Unity.Mathematics;
    8.  
    9. [UpdateAfter(typeof(ExportPhysicsWorld)), UpdateBefore(typeof(EndFramePhysicsSystem))]
    10. public class GameMangerDotstest : JobComponentSystem
    11. {        
    12.     BuildPhysicsWorld buildPhysicsWorld;
    13.     ExportPhysicsWorld exportPhysicsWorld;
    14.     EndFramePhysicsSystem endFramePhysics;
    15.    
    16.     protected override void OnCreate()
    17.     {
    18.         base.OnCreate();
    19.         buildPhysicsWorld = World.GetOrCreateSystem<BuildPhysicsWorld>();
    20.         exportPhysicsWorld = World.GetOrCreateSystem<ExportPhysicsWorld>();
    21.         endFramePhysics = World.GetOrCreateSystem<EndFramePhysicsSystem>();
    22.     }
    23.  
    24.     protected override JobHandle OnUpdate(JobHandle inputDeps)
    25.     {
    26.         float DeltaTime = Time.DeltaTime;
    27.         var physicsWorld = buildPhysicsWorld.PhysicsWorld;
    28.  
    29.         inputDeps = JobHandle.CombineDependencies(inputDeps, exportPhysicsWorld.FinalJobHandle);
    30.  
    31.         JobHandle jobhandle = Entities.WithAll<BoxTag>().WithReadOnly(physicsWorld).ForEach((ref Translation translation, ref LocalToWorld localtoworld, ref Rotation rotation, ref PhysicsVelocity velocity) =>
    32.         {
    33.  
    34.             float3 RayFrom = localtoworld.Value.c3.xyz;
    35.             float3 RayTo = RayFrom - (10 * localtoworld.Value.c1.xyz);
    36.  
    37.             RaycastInput input = new RaycastInput()
    38.             {
    39.  
    40.                 Start = RayFrom,
    41.                 End = RayTo,
    42.  
    43.                 Filter = new CollisionFilter
    44.                 {
    45.                     BelongsTo = ~0u,
    46.                     CollidesWith = ~0u,
    47.                     GroupIndex = 0
    48.                 }
    49.             };
    50.  
    51.             Unity.Physics.RaycastHit hit = new Unity.Physics.RaycastHit();
    52.             bool haveHit = physicsWorld.CastRay(input, out hit);
    53.  
    54.             if (haveHit)
    55.             {
    56.            
    57.                 translation.Value += 1f * localtoworld.Value.c2.xyz;
    58.             }
    59.             else
    60.             {
    61.  
    62.             }
    63.         }).Schedule(inputDeps);
    64.  
    65.         endFramePhysics.HandlesToWaitFor.Add(jobhandle);
    66.         return jobhandle;
    67.  
    68.     }
    69. }
     
    slushieboy99 and BeerCanAI like this.
  5. Michelle_Ca

    Michelle_Ca

    Joined:
    Aug 19, 2019
    Posts:
    113
    thank you very much desertGhost_ !
    this give an error before the start :
    C:\Dots game\ Assets\Dots Scripts\GameMangerDotstest.cs(31,9): error DC0034: Entities.WithReadOnly is called with an argument physicsWorld of unsupported type Unity.Physics.PhysicsWorld. It can only be called with an argument that is marked with [NativeContainerAttribute].

    I just copied the code as it and replaced it with the original, should I do something more to make it work?

    and please can you tell me where i can learn more about this stuff ?
     
    Last edited: Apr 26, 2020
  6. apaxnid

    apaxnid

    Joined:
    Nov 18, 2012
    Posts:
    35
    @
    Just remove .WithReadOnly(physicsWorld) you don't need it there. And you can use WithReadOnly only with native containers
     
    Michelle_Ca likes this.
  7. desertGhost_

    desertGhost_

    Joined:
    Apr 12, 2018
    Posts:
    260
    Which version of entities are you using? I'm using 0.9 with SystemBase and I can use WithReadOnly with PhysicsWorld.
     
  8. Michelle_Ca

    Michelle_Ca

    Joined:
    Aug 19, 2019
    Posts:
    113
    thank you apaxnid ! it works now
    desertGhost_ yes i'm useing 0.6 thats why did not work with WithReadOnly(physicsWorld) ,will it affect anything if I don’t put it on? The code is now working fine
    And does this code give a fixed timestep like FixedUpdate in MonoBehaviour ?if not how could i make it fixed step ?
     
  9. apaxnid

    apaxnid

    Joined:
    Nov 18, 2012
    Posts:
    35
    Oh they changed it. Sorry for disinformation than:p
     
    Michelle_Ca likes this.
  10. apaxnid

    apaxnid

    Joined:
    Nov 18, 2012
    Posts:
    35
    No, this code does not give you a fixed timestep. Look at FixedRateUtils.cs for fixed timestep
     
    Last edited: Apr 26, 2020
    Michelle_Ca likes this.
  11. Michelle_Ca

    Michelle_Ca

    Joined:
    Aug 19, 2019
    Posts:
    113
    okay i will check it out thanks a lot !!
     
  12. elJoel

    elJoel

    Joined:
    Sep 7, 2016
    Posts:
    125
    Thanks @desertGhost_ here's an updated version:

    Code (CSharp):
    1.     [UpdateAfter(typeof(ExportPhysicsWorld)), UpdateBefore(typeof(EndFramePhysicsSystem))]
    2.     public class RayCastSystem : JobComponentSystem
    3.     {      
    4.         BuildPhysicsWorld buildPhysicsWorld;
    5.         ExportPhysicsWorld exportPhysicsWorld;
    6.         EndFramePhysicsSystem endFramePhysics;
    7.      
    8.         protected override void OnCreate()
    9.         {
    10.             base.OnCreate();
    11.             buildPhysicsWorld = World.GetOrCreateSystem<BuildPhysicsWorld>();
    12.             exportPhysicsWorld = World.GetOrCreateSystem<ExportPhysicsWorld>();
    13.             endFramePhysics = World.GetOrCreateSystem<EndFramePhysicsSystem>();
    14.         }
    15.    
    16.         protected override JobHandle OnUpdate(JobHandle inputDeps)
    17.         {
    18.             var physicsWorld = buildPhysicsWorld.PhysicsWorld;
    19.    
    20.             inputDeps = JobHandle.CombineDependencies(inputDeps, exportPhysicsWorld.GetOutputDependency());
    21.    
    22.             var jobHandle = Entities.WithReadOnly(physicsWorld).ForEach((ref LocalToWorld localToWorld, ref RayCastTag rayCast) =>
    23.             {
    24.                 var rayFrom = localToWorld.Value.c3.xyz;
    25.                 var rayTo = rayFrom - (rayCast.Length * localToWorld.Value.c1.xyz);
    26.    
    27.                 RaycastInput input = new RaycastInput()
    28.                 {
    29.    
    30.                     Start = rayFrom,
    31.                     End = rayTo,
    32.    
    33.                     Filter = new CollisionFilter
    34.                     {
    35.                         BelongsTo = ~0u,
    36.                         CollidesWith = ~0u,
    37.                         GroupIndex = 0
    38.                     }
    39.                 };
    40.  
    41.                 bool haveHit = physicsWorld.CastRay(input, out _);
    42.                 if (haveHit)
    43.                 {
    44.                     UnityEngine.Debug.Log("Hit");
    45.                     // translation.Value += 1f * localtoworld.Value.c2.xyz;
    46.                 }
    47.                 else
    48.                 {
    49.                     UnityEngine.Debug.Log("No Hit");
    50.    
    51.                 }
    52.             }).Schedule(inputDeps);
    53.    
    54.             endFramePhysics.AddInputDependency(jobHandle);
    55.             return jobHandle;
    56.         }
    57.  
     
  13. MNNoxMortem

    MNNoxMortem

    Joined:
    Sep 11, 2016
    Posts:
    723
    @elJoel do you have a working version for the latest packages? Your RayCastSystem throws for me with the latest packages:
    Code (CSharp):
    1. InvalidOperationException: The previously scheduled job RaycastSystem:<>c__DisplayClass_OnUpdate_LambdaJob0 reads from the Unity.Collections.NativeArray`1[Unity.Physics.CollisionFilter] <>c__DisplayClass_OnUpdate_LambdaJob0.JobData.physicsWorld.CollisionWorld.Broadphase.m_StaticTree.BodyFilters. You are trying to schedule a new job Broadphase:PrepareStaticBodyDataJob, which writes to the same Unity.Collections.NativeArray`1[Unity.Physics.CollisionFilter] (via PrepareStaticBodyDataJob.FiltersOut). To guarantee safety, you must includ
    2. InvalidOperationException: Adding/removing components or changing position/rotation/velocity/collider ECS data on dynamic entities during physics step
    3.  
     
  14. elJoel

    elJoel

    Joined:
    Sep 7, 2016
    Posts:
    125
    The only change you need is removing the first line:
    Code (CSharp):
    1.    [UpdateAfter(typeof(ExportPhysicsWorld)), UpdateBefore(typeof(EndFramePhysicsSystem))]
     
    MNNoxMortem likes this.