Search Unity

Question Unable to raycast upward? Or: unable to detect raycast hit from beneath a surface?

Discussion in 'Scripting' started by lemmons, Apr 7, 2021.

  1. lemmons

    lemmons

    Joined:
    Jun 20, 2016
    Posts:
    68
    Trying to snap objects to the surface of my terrain whether they're above or below it. I followed this handy video to get started. But in my game, objects can drift far above and below the terrain so I tried to modify it a bit and just can't figure out what the deal is.

    In the video, he adjusts the origin of the ray to be slightly above the object by using + Vector3.up. So in this example, I modified it a bit to have a slightly larger range. This code works whether the object is above or below as long as they're within the range.

    Code (CSharp):
    1.                 LayerMask groundMask = LayerMask.GetMask("Ground");
    2.         foreach (var transform in Selection.transforms)
    3.         {
    4.             var hits = Physics.RaycastAll(transform.position + Vector3.up * 10f, Vector3.down, 50f, groundMask);
    5.             foreach(var hit in hits)
    6.             {
    7.                 transform.position = hit.point;
    8.                 break;
    9.             }
    10.         }
    But it felt hacky so I decided to do a Raycast down and if that didn't find anything to do a Raycast up. Using pretty much the exact same code for each, when an object is above the terrain it works but when the object is below the terrain the raycast in the if statement never returns true. I've tried using `transform.up` instead of `Vector3.up` to no avail as well.
    Code (CSharp):
    1.         LayerMask groundMask = LayerMask.GetMask("Ground");
    2.         RaycastHit raycastHit;
    3.  
    4.         foreach (var transform in Selection.transforms)
    5.         {
    6.             if (Physics.Raycast(transform.position, Vector3.down, out raycastHit, 50f, groundMask))
    7.             {
    8.                 transform.position = raycastHit.point;
    9.             }
    10.             else if (Physics.Raycast(transform.position, Vector3.up, out raycastHit, 50f, groundMask))
    11.             {
    12.                 transform.position = raycastHit.point;
    13.             }
    14.         }
    So are you unable to raycast upward or does it have to do with not being able to detect a raycast hit on the bottom of a surface?
     
  2. lordofduct

    lordofduct

    Joined:
    Oct 3, 2011
    Posts:
    8,532
    It depends on your collider.

    If you have a MeshCollider, and that mesh is not flagged to be convex, and the mesh itself is one way... the physics is also one way.

    Another could be if you're "inside" the collider, raycast does not work from inside out. Note this impacts things like meshcolliders that are flagged as convex, because if it's undulating terrain the convex collider will actually try to fill in any concave regions creating a solid meaning it has an "inside".

    And of course with box and sphere colliders, they have insides since they're inherently convex.
     
    lemmons likes this.
  3. lemmons

    lemmons

    Joined:
    Jun 20, 2016
    Posts:
    68
    Ahh, that makes sense. I'm using Terrain Tools and by default I don't have the option to make it convex so I'll just try to be smart about how far below the ground my objects can go. Thanks again @lordofduct!