Search Unity

Question collider out of position when use Unity.Physics raycast

Discussion in 'Physics for ECS' started by ankd, Aug 3, 2020.

  1. ankd

    ankd

    Joined:
    Aug 22, 2017
    Posts:
    5
    I want to click on an entity to get it.
    There are several spheres in the scene with ConvertToEntity attached. One is at the origin, the other is outside the scene origin. And I'm trying to implement raycast using Unity.Physics.
    It referenced from here:
    https://docs.unity3d.com/Packages/com.unity.physics@0.4/manual/collision_queries.html#ray-casts

    It works fine for the origin entity, but for other entities the collider appears to be offset from the origin in the direction of the position vector.
    The offset seems to increase with distance from the origin to entity or/and distance from camera to entity.
    What cause the offset?

    Or if you know the best practice of clicking to select entities, please let me know.

    figure.
    1, 2 : Collider region of the spherical entity at (3,3,0). It seems to be shifted to the upper right.
    3 : The offset increases as the camera moves away.

    Snipaste_2020-08-03_13-40-46.png Snipaste_2020-08-03_13-41-33.png Snipaste_2020-08-03_13-42-13.png
     
  2. petarmHavok

    petarmHavok

    Joined:
    Nov 20, 2018
    Posts:
    461
  3. ankd

    ankd

    Joined:
    Aug 22, 2017
    Posts:
    5
    What do you mean "at individual spheres or at the world"?

    Thank you for show me the sample project.
    I see it, it seems to do same things, especially
    struct Pick : IJob

    But my project is much more simple than the sample.
    I want to click entity and add or remove tag component of it, so at first I only try to pick entity by clicking.

    The figure in the first post shows how the mouse may point to an entity but not be a hit, or it may not point to an entity but be a hit.
    The sample project can be picked entity when click anywhere of the entity correctly but my project return Incorrect result.

    I show my source code.
    I want to get the entity in not only Entities.ForEach but also MonoBehaviour script.
    So in the sample project the code implemented as Job System but in my project it's implemented as MonoBehaviour script.

    Code (CSharp):
    1. using UnityEngine;
    2. using Unity.Entities;
    3. using Unity.Mathematics;
    4. using Unity.Physics;
    5.  
    6. public class ECSRaycaster : MonoBehaviour
    7. {
    8.     void Update()
    9.     {
    10.         UnityEngine.Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    11.         float rayDistance = 100f;
    12.         Entity hitEntity = Raycast(ray.origin, ray.direction * rayDistance);
    13.         if (hitEntity != Entity.Null)
    14.         {
    15.             Debug.Log("Hit");
    16.         } else {
    17.             Debug.Log("No Hit");
    18.         }
    19.     }
    20.  
    21.     // copy from: https://docs.unity3d.com/Packages/com.unity.physics@0.4/manual/collision_queries.html#ray-casts
    22.     public Entity Raycast(float3 RayFrom, float3 RayTo)
    23.     {
    24.         var physicsWorldSystem = World.DefaultGameObjectInjectionWorld.GetExistingSystem<Unity.Physics.Systems.BuildPhysicsWorld>();
    25.         var collisionWorld = physicsWorldSystem.PhysicsWorld.CollisionWorld;
    26.         RaycastInput input = new RaycastInput()
    27.         {
    28.             Start = RayFrom,
    29.             End = RayTo,
    30.             Filter = new CollisionFilter()
    31.             {
    32.                 BelongsTo = ~0u,
    33.                 CollidesWith = ~0u, // all 1s, so all layers, collide with everything
    34.                 GroupIndex = 0
    35.             }
    36.         };
    37.  
    38.         Unity.Physics.RaycastHit hit = new Unity.Physics.RaycastHit();
    39.         bool haveHit = collisionWorld.CastRay(input, out hit);
    40.         if (haveHit)
    41.         {
    42.             // see hit.Position
    43.             // see hit.SurfaceNormal
    44.             Entity e = physicsWorldSystem.PhysicsWorld.Bodies[hit.RigidBodyIndex].Entity;
    45.             return e;
    46.         }
    47.         return Entity.Null;
    48.    }
    49. }
    50.  
     
  4. petarmHavok

    petarmHavok

    Joined:
    Nov 20, 2018
    Posts:
    461
    Ignore my question, you are querying the world, it's clear from the code. Your code seems fine. It could be that the setup is wrong, for example in your PhysicsShapeAuthoring is there an additional transform on the sphere collider? For example, if you put center of the sphere a little bit offset, it will add that transform to the entity transform and your collider will be a little offset.

    If you turn on debug display code in the Physics Scene Basic Elements prefab that comes with every scene in the samples (specifically turn on Draw Colliders on Physics Settings) you can see where physics sees your colliders and if they are offset a bit.
     
  5. ankd

    ankd

    Joined:
    Aug 22, 2017
    Posts:
    5
    I haven't moved the Sphere Collider.
    I've checked the collider using Physics Debug Display and it doesn't seem to have an offset (I'm really surprised).

    I changed the component from a sphere collider to a Physics Shape and Physics Body, but nothing happens.

    Then check the ray by adding the following code:
     Debug.DrawRay (ray.origin, ray.direction * rayDistance, Color.red);
    It looks like it hits a collider, but it's not a hit.

    I can't understand why that happened...

    Snipaste_2020-08-04_10-38-05.png
     
  6. petarmHavok

    petarmHavok

    Joined:
    Nov 20, 2018
    Posts:
    461
    I'm assuming you are not stepping the world? Or you just disabled gravity?

    Are you using the BuildPhysicsWorld system? It is supposed to do a build of the bounding volume hierarchy for you, so that queries can work.
     
  7. PrarR

    PrarR

    Joined:
    Mar 23, 2020
    Posts:
    1
    Although the post is old, I came across it while searching for a solution to a similar problem. The solution for me was to type the following code for RaycastInput -> End (note - in the scene preview, Debug.DrawRay is totally unlogic, but the result is correct (feature logic is working)):

    Code (CSharp):
    1. End = ray.origin + ray.direction * rayLength