Search Unity

  1. If you have experience with import & exporting custom (.unitypackage) packages, please help complete a survey (open until May 15, 2024).
    Dismiss Notice
  2. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice

World.CastCollider(CastColliderInput, NativeList<ColliderCastHit>) in parallel job?

Discussion in 'Entity Component System' started by Fluidmind, Jun 11, 2020.

  1. Fluidmind

    Fluidmind

    Joined:
    Jan 10, 2020
    Posts:
    28
    So, I have a system that I want to run as a entity-based gravity simulation, but due to the potential population of the gravity wells, I wanted to run each well through their own thread. Anyways, my code is below. Can anyone recommend an alternative, or create a new overload that would work in this manner?

    Code (CSharp):
    1.  
    2. using Unity.Collections;
    3. using Unity.Collections.LowLevel.Unsafe;
    4. using Unity.Entities;
    5. using Unity.Jobs;
    6. using Unity.Mathematics;
    7. using Unity.Physics;
    8. using Unity.Physics.Systems;
    9. using Unity.Transforms;
    10.  
    11.  
    12.  
    13. [GenerateAuthoringComponent]
    14. public struct SphericalGravityEmitter : IComponentData
    15. {
    16.     public float gravityForce;
    17.     public float radius;
    18. }
    19.  
    20. //iterate gravity wells
    21. //grab entities and measure distance
    22. //always a multiplier problem? could I not just construct a mesh and run the trigger on those?
    23.  
    24.  
    25. [UpdateBefore(typeof(BuildPhysicsWorld))]
    26. public class GravitySystem : JobComponentSystem
    27. {
    28.     NativeArray<Entity> SphericalGravityEntities;
    29.     ComponentDataFromEntity<SphericalGravityEmitter> emitterData;
    30.     EntityQuery emitters;
    31.  
    32.     unsafe struct RunGravity : IJobParallelFor
    33.     {
    34.         [WriteOnly] public ComponentDataFromEntity<PhysicsVelocity> entityVelocities;
    35.         [ReadOnly] public CollisionWorld world;
    36.         [ReadOnly] public float dt;
    37.         [ReadOnly] public ComponentDataFromEntity<SphericalGravityEmitter> _emitterData;
    38.         [ReadOnly] public ComponentDataFromEntity<Translation> pos;
    39.         [ReadOnly] public NativeArray<Entity> SphericalGravityEntities;
    40.        
    41.         [WriteAccessRequired]
    42.         unsafe public void Execute(int index)
    43.         {
    44.             NativeList<ColliderCastHit> affectedEntities = new NativeList<ColliderCastHit>();
    45.             /* setup emitter */
    46.             Entity thisEmitter = SphericalGravityEntities[index];
    47.             float3 thisEmitterPos = pos[thisEmitter].Value;
    48.             float thisEmitterRadius = _emitterData[thisEmitter].radius;
    49.             float thisEmitterForce = _emitterData[thisEmitter].gravityForce;
    50.             /* end setup emitter */
    51.  
    52.             /* run collider cast to grab subject entities */
    53.             BlobAssetReference<Collider> gravityWell = SphereCollider.Create(new SphereGeometry
    54.             {
    55.                 Center = float3.zero,
    56.                 Radius = thisEmitterRadius
    57.             });
    58.             ColliderCastInput gravityWells = new ColliderCastInput()
    59.             {
    60.                 Collider = (Collider*)gravityWell.GetUnsafePtr(),
    61.                 Orientation = quaternion.identity,
    62.                 Start = pos[thisEmitter].Value,
    63.                 End = pos[thisEmitter].Value * 0.001f
    64.             };
    65.             /* end collider */
    66.  
    67.             /* if nothing's in the gravity well, stop. */
    68.             if (world.CastCollider(gravityWells, ref affectedEntities))
    69.                 /* also, I love that Unity has this assembly function that represents just
    70.                  * a chainsaw calculator for sphere casting, even if you have to work in unsafe space.
    71.                  */
    72.             {
    73.                 /* iterate gravity subjects */
    74.                 for (int i = 0; i < affectedEntities.Length; i++)
    75.                 {
    76.                     /* setup gravity subject */
    77.                     Entity thisEntity = world.Bodies[affectedEntities[i].RigidBodyIndex].Entity;
    78.                     float3 thisEntityPos = pos[thisEntity].Value;
    79.                     /* end etup gravity subject */
    80.  
    81.                     /* Calulate the force vector */
    82.                     float distance = math.dot(thisEmitterPos, thisEntityPos);
    83.                     float3 distanceVector = thisEmitterPos - thisEntityPos;
    84.                     float3 unitVector = distanceVector / distance;
    85.                     float3 thisForce = (thisEmitterForce * ((thisEmitterRadius - distance) / thisEmitterRadius));
    86.                     thisForce = math.normalizesafe(thisForce, thisForce);
    87.                     /* force vector in thisForce */
    88.  
    89.                     /* apply force? */
    90.                     PhysicsVelocity pv = entityVelocities[thisEntity];
    91.                     pv.Linear += thisForce * dt;
    92.                     entityVelocities[thisEntity] = pv;
    93.                 }
    94.             }
    95.             affectedEntities.Dispose();
    96.         }
    97.     }
    98.  
    99.     protected override void OnCreate()
    100.     {
    101.         emitters = GetEntityQuery(ComponentType.ReadOnly<SphericalGravityEmitter>());
    102.         emitterData = GetComponentDataFromEntity<SphericalGravityEmitter>();
    103.     }
    104.  
    105.     protected override void OnDestroy()
    106.     {
    107.         if (SphericalGravityEntities.IsCreated)
    108.         {
    109.             SphericalGravityEntities.Dispose();
    110.         }
    111.     }
    112.  
    113.     protected override JobHandle OnUpdate(JobHandle inputDeps)
    114.     {
    115.         emitterData = GetComponentDataFromEntity<SphericalGravityEmitter>();
    116.         JobHandle getEmitters;
    117.         if (SphericalGravityEntities.IsCreated)
    118.         {
    119.             SphericalGravityEntities.Dispose();
    120.         }
    121.         SphericalGravityEntities = emitters.ToEntityArrayAsync(Allocator.TempJob, out getEmitters);
    122.         inputDeps = JobHandle.CombineDependencies(inputDeps, getEmitters);
    123.         JobHandle ApplyGravity = new RunGravity
    124.         {
    125.             entityVelocities = GetComponentDataFromEntity<PhysicsVelocity>(),
    126.             _emitterData = GetComponentDataFromEntity<SphericalGravityEmitter>(),
    127.             pos = GetComponentDataFromEntity<Translation>(),
    128.             SphericalGravityEntities = SphericalGravityEntities,
    129.             world = World.GetExistingSystem<BuildPhysicsWorld>().PhysicsWorld.CollisionWorld,
    130.             dt = Time.DeltaTime
    131.         }.Schedule(emitters.CalculateEntityCount(),10,inputDeps);
    132.  
    133.         return ApplyGravity;
    134.     }
    135. }
    136.