Search Unity

Equivalent of 3D Collider.Raycast

Discussion in '2D' started by Baste, Jun 22, 2021.

  1. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,338
    Both 2D and 3D physics has Raycast methods on the Collider type, but they're very different beasts:

    Collider2D.Raycast:
    "Casts a ray into the Scene that starts at the Collider position and ignores the Collider itself."

    Collider.Raycast:
    "Casts a Ray that ignores all Colliders except this one."

    Does 2D physics have something akin to the 3D version that I can't find? I can work around it by doing a raycast against everything and then manually filtering out hits that are not the collider I care about, but I assume that that's slower, and it's also a bit clunky.
     
  2. MoonJellyGames

    MoonJellyGames

    Joined:
    Oct 2, 2014
    Posts:
    331
    If I'm understanding correctly, you just want to limit which types of objects your raycast hits, yes? One of the parameters of the Raycast function is layerMask, which is super helpful. You just need to make sure you're managing your physics layers.

    Hopefully that helps a little. :)
     
  3. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,491
    The is the very first time I've had this request and it does seem like a very niech call too TBH. 2D physics uses the call on that collider to remove the need to calculate its position as the starting point with the option of ignoring that collider. This, early on, was a widely requested feature often used for projecting rays from a character to its environment ignoring the collider itself.

    That's not to say it cannot be added but I do think calling i If I were to add it, I'd add it to the ContactFilter2D so that all 2D physics queries would get the ability to include or exclude a specific Collider2D and not just a specific overload of a Raycast.

    In the end, 3D physics isn't a golden standard API so not everything is copied but instead, if there's enough requests or we can see a wider utility in implementing something that also satisfies other needs then it'll likely get added.

    I cannot think of a simple way to emulate that feature though TBH. I mean there's ClosestPoint but if you're more interested in that specific direction then it's obviously not going to help. Only option is to filter by layers to reduce the potentials and then look for that collider.
     
    Last edited: Jun 24, 2021
  4. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,338
    It's also pretty common for us to use something like it. If you want to do a thing like "place flowers randomly on a terrain", you'd raycast from above down against the terrain mesh instead of the entire scene. Or if you want a character's hand to IK to the closest point on on an interactable object, you'd want to raycast from the hand against the object, not the world.

    I needed it for 2D as I wanted to place something on a spriteshape, and the only thing I cared about for the placement was the SpriteShape's edge collider, not any object that may potentially be in the way.


    All that being said, I suspect 3D has it because it should be way faster to check against a single collider than the entire scene graph. If your ContactFilter-based implementation would basically be "do a raycast all, look for the asked for collider, return the matching hit if there is one", we can just make that extension method for ourselves, no biggie.

    It's more that the 2D API for the most part is a direct mapping to the 3D API - so the same methods exist and they do the same thing. When we then suddenly run into a method that does the exact opposite thing, but with the same name, it does throw us for a loop.
     
  5. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,491
    It's easy to forgot that your raycast isn't just going to be against a single primitive shape collider such as circle, capsule etc. Box2D has TestPoint and Raycast against primitive shapes only. Take the CompositeCollider2D, TilemapCollider2D or the new CustomCollider2D; those might be composed of tens of thousands of primitives so performing raycast against each primitive shape would take a lot of time and Unity colliders don't have their own "scene graph". Each primitive shape is in the Box2D broadphase and we hook into the low-level algorithm that navigates the broadphase so it's super low-level and very fast. It doesn't get all the hits then perform some post-processing step to filter them out. This is far faster than anything you could do in script returning all results, getting them in a list, searching for a specific collider etc. These results wouldn't go beyond seeing a pointer to a primitive shape, seeing if has a pointer to the Unity collider then accepting it or discounting it.

    The ContactFilter2D when set to filter a specific Collider2D would encounter primitives shapes in the broadphase and convert the pointer we have to the Unity collider and check it then ignore it if required. The additional benefit as I've said is that it'll natural work on every single query and not just raycast.
     
  6. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,491
    I would add that this view is quite skewed towards saying bad performance when in reality it's not a case of doing this against a single collider or every collider but instead it's far more common to filter by "ground" i.e. a layer approach. I know you know this but I wanted that to be clear for anyone else reading this too.

    This isn't to say at all that I'm pushing against your idea; quite the opposite in-fact!
     
    Last edited: Jun 25, 2021
  7. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,338
    There's a completely unrelated discussion to be had about "when are you going to give us rendering layers and collision layers that are independent?", since that's usually why we don't just make a layer to do something - they're limited, and both 2D and 3D lights filter by what they hit or not.

    If I make a thing that cares about objects rather than layers, I can be sure that it doesn't interact with other systems. Whenever a layer's involved, I immediately introduce some fragility there that I'd rather not. We've gotten better at it over the years, but when we were starting out there was a lot of bugs of the form "the artist moved the object to a different layer so it would look correct, so now it's not colliding with the correct things" or "the level designer moved the object to a different layer so it would collide correctly, but now it looks wrong".



    That does sound appealing, for sure!
     
  8. MelvMay

    MelvMay

    Unity Technologies

    Joined:
    May 24, 2013
    Posts:
    11,491
    I completely agree (lots of nodding going on here) but it's something that would be independently 2D physics and/or 3D physics too. I can tell you now that we've got a road-map for 2D physics that includes designs for looking how to provide a different approach to defining interactions moving away from layers which are, as you suggest, an overloaded concept. The "ball and chain" in this design is the overwhelming amount of existing practices and materials surrounding the layer-based approach which means we must be able to switch between models or, as in our design, allow them to compliment each other.
     
    Baste likes this.