Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Raycasts not behaving correctly

Discussion in 'Entity Component System' started by Khujo, Oct 18, 2019.

  1. Khujo

    Khujo

    Joined:
    Feb 14, 2012
    Posts:
    9
    I've been porting over a script to ecs that handles some rudimentary pathfinding. Everything worked great until I switched to the new Unity physics package. The ray-casts are firing and colliding; however, they're behaving unexpectedly. (i.e. hitting when they shouldn't be, and not hitting when they should).

    1. I'd typically do a Debug.DrawRay to ensure they're aimed how I want. Is there an equivalent I could use?

    2. Here's a trimmed down version of the code, there may be an issue I'm not picking up on.

    Code (CSharp):
    1. public class PathfindingSystem : JobComponentSystem {
    2.  
    3.     BuildPhysicsWorld physicsWorld;
    4.  
    5.     protected override void OnCreate() {
    6.         physicsWorld = World.GetOrCreateSystem<BuildPhysicsWorld>();
    7.     }
    8.  
    9.     [BurstCompile]
    10.     struct PathfindingSystemJob : IJobForEach<Translation, PathfindingComponent, Rotation, LocalToWorld> {
    11.         [ReadOnly] public float deltaTime;
    12.         [ReadOnly] public CollisionWorld collisionWorld;
    13.  
    14.         public void Execute(ref Translation translation, ref PathfindingComponent pathfindingComponent, ref Rotation rotation, ref LocalToWorld localToWorld) {
    15.  
    16.             RaycastInput up = new RaycastInput() {
    17.                 Start = translation.Value + localToWorld.Up * pathfindingComponent.rayCastOffset,
    18.                 End = localToWorld.Forward * pathfindingComponent.detectionDistance,
    19.                 Filter = CollisionFilter.Default
    20.             };
    21.  
    22.             var offset = Vector3.zero;
    23.  
    24.             // Emit raycasts
    25.             if (collisionWorld.CastRay(up)) {
    26.                 offset -= Vector3.up;
    27.                 //Debug.Log("hit up");
    28.             }
    29.  
    30.             if (offset != Vector3.zero) {
    31.                 // Avoid obstacle
    32.             } else {
    33.                 // No obstacle, turn towards target
    34.             }
    35.         }
    36.     }
    37.  
    38.     protected override JobHandle OnUpdate(JobHandle inputDependencies) {
    39.         var job = new PathfindingSystemJob();
    40.         job.deltaTime = Time.deltaTime;
    41.         job.collisionWorld = physicsWorld.PhysicsWorld.CollisionWorld;
    42.  
    43.         return job.Schedule(this, inputDependencies);
    44.     }
    45. }
     
  2. Rory_Havok

    Rory_Havok

    Joined:
    Jun 25, 2018
    Posts:
    70
    Looks like your RaycastInput.End is a direction not an endpoint.
     
  3. eizenhorn

    eizenhorn

    Joined:
    Oct 17, 2016
    Posts:
    2,683
    @Rory_Havok right. Why you using Direction in End if it's even named as point :) And if you look at sources you'll see it converts it to Direction, and comments describes that Start nad End is points :)
    Code (CSharp):
    1. // The input to ray cast queries consists of
    2.     // the Start & End positions of a line segment,
    3.     // and a CollisionFilter used to cull potential hits
    4.     public struct RaycastInput
    5.     {
    6.         public float3 Start
    7.         {
    8.             get => Ray.Origin;
    9.             set
    10.             {
    11.                 float3 end = Ray.Origin + Ray.Displacement;
    12.                 Ray.Origin = value;
    13.                 Ray.Displacement = end - value;
    14.             }
    15.         }
    16.         public float3 End
    17.         {
    18.             get => Ray.Origin + Ray.Displacement;
    19.             set => Ray.Displacement = value - Ray.Origin;
    20.         }
    21.  
    22.         public CollisionFilter Filter;
    23.  
    24.         internal Ray Ray;
    25.     }
     
  4. Khujo

    Khujo

    Joined:
    Feb 14, 2012
    Posts:
    9
    I knew I was missing something! Thanks for the help.

    Sharing is caring. Here's where I ended up for anyone interested.

    Code (CSharp):
    1. using Unity.Burst;
    2. using Unity.Entities;
    3. using Unity.Jobs;
    4. using UnityEngine;
    5. using Unity.Transforms;
    6. using Unity.Mathematics;
    7. using Unity.Physics.Systems;
    8. using Unity.Collections;
    9. using Unity.Physics;
    10.  
    11. public class PathfindingSystem : JobComponentSystem {
    12.  
    13.     BuildPhysicsWorld physicsWorld;
    14.  
    15.     protected override void OnCreate() {
    16.         physicsWorld = World.GetOrCreateSystem<BuildPhysicsWorld>();
    17.     }
    18.  
    19.     [BurstCompile]
    20.     struct PathfindingSystemJob : IJobForEach<Translation, PathfindingComponent, Rotation, LocalToWorld> {
    21.         [ReadOnly] public float deltaTime;
    22.         [ReadOnly] public float3 target;
    23.         [ReadOnly] public CollisionWorld collisionWorld;
    24.  
    25.         public void Execute(ref Translation translation, ref PathfindingComponent pathfindingComponent, ref Rotation rotation, ref LocalToWorld localToWorld) {
    26.  
    27.             Vector3 end = math.forward(rotation.Value) * pathfindingComponent.detectionDistance;
    28.  
    29.             NativeArray<PathfindingRay> rays = new NativeArray<PathfindingRay>(4, Allocator.Temp);
    30.             rays[0] = new PathfindingRay(translation.Value - localToWorld.Right * pathfindingComponent.rayCastOffset, end, Vector3.right);    // Left
    31.             rays[1] = new PathfindingRay(translation.Value + localToWorld.Right * pathfindingComponent.rayCastOffset, end, Vector3.left);    // Right
    32.             rays[2] = new PathfindingRay(translation.Value + localToWorld.Up * pathfindingComponent.rayCastOffset, end, Vector3.down);        // Up
    33.             rays[3] = new PathfindingRay(translation.Value - localToWorld.Up * pathfindingComponent.rayCastOffset, end, Vector3.up);        // Down
    34.  
    35.             var offset = Vector3.zero;
    36.  
    37.             // Emit raycasts
    38.             for (var i = 0; i < rays.Length; i++) {
    39.                 if (collisionWorld.CastRay(rays[i].ray)) {
    40.                     // Apply counter adjustment to avoid
    41.                     offset += rays[i].counterAdjustment;
    42.                     break;
    43.                 }
    44.             }
    45.  
    46.             if (offset != Vector3.zero) {
    47.                 // Avoid obstacle
    48.                 var newVal = math.mul(math.normalize(rotation.Value), quaternion.EulerXYZ(offset));
    49.                 rotation.Value = Quaternion.Slerp(rotation.Value, newVal, pathfindingComponent.rotationalDamp * deltaTime);
    50.             } else {
    51.                 // No obstacle, turn towards target
    52.                 Vector3 pos = target - translation.Value;
    53.                 Quaternion newRotation = Quaternion.LookRotation(pos);
    54.                 rotation.Value = Quaternion.Slerp(rotation.Value, newRotation, pathfindingComponent.rotationalDamp * deltaTime);
    55.             }
    56.  
    57.             // Move forward
    58.             translation.Value += math.forward(rotation.Value) * deltaTime * pathfindingComponent.movementSpeed;
    59.  
    60.             rays.Dispose();
    61.         }
    62.     }
    63.  
    64.     protected override JobHandle OnUpdate(JobHandle inputDependencies) {
    65.         var job = new PathfindingSystemJob();
    66.         job.deltaTime = Time.deltaTime;
    67.         job.collisionWorld = physicsWorld.PhysicsWorld.CollisionWorld;
    68.  
    69.         var targets = GetEntityQuery(typeof(TargetComponent), typeof(Translation)).ToComponentDataArray<Translation>(Allocator.Persistent);
    70.  
    71.         if(targets.Length > 0) {
    72.             job.target = targets[0].Value;
    73.         }
    74.  
    75.         targets.Dispose();
    76.  
    77.         return job.Schedule(this, inputDependencies);
    78.     }
    79. }
    80.  
    81. public struct PathfindingRay {
    82.     public RaycastInput ray;
    83.     public Vector3 counterAdjustment;
    84.  
    85.     public PathfindingRay(Vector3 start, Vector3 end, Vector3 counterAdjustment) {
    86.         ray = new RaycastInput() {
    87.             Start = start,
    88.             End = start + end,
    89.             Filter = CollisionFilter.Default
    90.         };
    91.         this.counterAdjustment = counterAdjustment;
    92.     }
    93. }