Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question Physics.queriesHitBackfaces doesn't work?

Discussion in 'Scripting' started by ml785, Dec 22, 2022.

  1. ml785

    ml785

    Joined:
    Dec 20, 2018
    Posts:
    109


    second angle:


    Hi,
    I have 2 Raycasts traveling downwards, from inside a brown Cube mesh.
    (the Raycasts are color white. the RaycastHit points are indicated by green X's)

    I have `Physics.queriesHitBackfaces = true;` in my script. I also have the option turned on in Project Settings -> Physics.

    However, the Raycasts are still ignoring the face of the cube they're inside, and instead are traveling through it and hitting a different cube on the outside (the green cube).

    How would I make the Raycasts hit the faces of the brown cube from inside of it?
    and why wouldn't the `Physics.queriesHitBackfaces = true;` code be sufficient?
    (Sidenote- I've seen search results claiming `Physics.queriesHitBackfaces` is bugged for some Unity versions so maybe that's happening here. I have tested on `Unity 2022.2.1f1` and `Unity 2021.2.8f1`.)
     
    Last edited: Dec 22, 2022
  2. tomekkie2

    tomekkie2

    Joined:
    Jul 6, 2012
    Posts:
    949
    If it is still bugged - I guess you could workaround the problem by RaycastAll along a reversed ray directed from infinity to the current origin, and picking the farthest hit from the results.
     
  3. burningmime

    burningmime

    Joined:
    Jan 25, 2014
    Posts:
    845
    Is the brown cube a MeshCollider or a BoxCollider?
     
    angrypenguin likes this.
  4. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,509
    According to the docs, bold emphasis mine:
    If you're using a box collider then it's not made of triangles, it's a primitive box shape, so there aren't any "backfaces" to hit. If you swap it for a MeshCollider then I suspect it would work.

    Probably the docs should be clearer that this applies only to MeshColliders, as from what's written someone wouldn't necessarily draw the distinction just from the word "triangles".
     
    Bunny83, INeatFreak and tomekkie2 like this.
  5. tomekkie2

    tomekkie2

    Joined:
    Jul 6, 2012
    Posts:
    949
    One might expect if you raycastAll a primitive like cube, sphere, cone, prism - then with
    Physics.queriesHitBackfaces = true

    you should get two hits:
    • one for entering the mesh, for the front face
    • second for leaving the mesh, for the back face
    But I am getting only one result for the front face and the Raycast is ignoring the back face in this case.
     
    angrypenguin likes this.
  6. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,509
    Thanks for confirming. For anyone trying to solve this...

    Short version:
    Either use a MeshCollider, or do a second Raycast against your primitive from the other side pointing backwards.

    Long version:
    Putting aside the wording of the documentation, a primitive collider isn't what you need. You need a MeshCollider, or a bit of custom logic.

    Why? I haven't read the code to confirm, but given the shape of primitive colliders, rays, etc. and the requirement for performance I would assume that the system is internally built around the assumption that each primitive can have a single contact with each other primitive / ray. Most of the time this is indeed what we care about, and other cases can still be addressed (see the alternatives below), so that's the case the physics system is built around.

    A MeshCollider is not a "primitive". It can represent concave and disjoint shapes, which introduces all sorts of complexity. In particular, it violates the assumption that it can only have a single contact with another primitive. Because of this its implementation is pretty different.

    Internally it is a structure which holds a bunch of triangles. Each individual triangle is a primitive which fits the assumption described above. Triangles also have a couple of interesting properties compared to the other primitive shapes:
    - Each one is perfectly flat.
    - The entry point is also the exit point of a ray.
    With these in mind, if you compose a complex shape out of triangles, then you can use this to approximate all entry/exit points by performing primitive checks against the individual triangles. Usually you only care about your ray "entering" an object, which is where the term "backface" comes into play. A backface is a triangle that is facing away from you, and usually you only care about ones facing towards you. However, there are quite a few cases where it's useful to include triangles which are facing away from you, hence inclusion of that option.

    I know that the documentation is a little vague, but I believe that is specifically what that "queriesHitBackfaces" setting is all about. As humans we conceptualise a cube as having 6 faces, but to a computer it has no faces - it is a volume defined by a position and a set of extents. A sphere isn't an infinite number of faces, it's a point and a radius, and so on. I suspect that's exactly how the physics developers consider it, too!

    Alternatives for calculating the exit point on a primitive:
    - You can create an opposing ray on the through-side of the primitive pointing backwards, and cast against just that primitive (IIRC the collider has a Raycast function). This will get you the exit point, with fairly simple code that'll be identical across all primitive types. This works because, being a primitive, the collider is convex.

    - Re-create the primitive as a mesh, and use this as your collider. (You might even be able to drag the Renderer's mesh into the MeshCollider in the Inspector.)

    - You could do the math to figure out the exit point yourself. This might* be the most efficient method, though it would require different math for each type of primitive, so it'd be a bit of a pain to implement if you need to support a bunch of types. And even if* it's more efficient, unless you're doing this a lot the difference is unlikely to be of concern.

    * I haven't tested it, as it has never mattered to me.
     
    Bunny83 and spiney199 like this.
  7. tomekkie2

    tomekkie2

    Joined:
    Jul 6, 2012
    Posts:
    949
    Note that in my statement I meant not Unity primitives, but general primitives, including primitives imported from 3d program with mesh collider creation option.
    Regarding Unity primitives you can also remove the "dedicated" colliders and attach mesh colliders instead.

    Regarding the
    Physics.queriesHitBackfaces = true;

    statement you can see difference
    • on single sided objects like quads and planes.
    • on primitives with inverted normals - it determines which face is detected, but still only one face is detected and other gets ignored
    • on rays casted from inside of mesh like it was already mentioned before
     
  8. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,524
    That's a complete misuse of the term primitive then. Primitive colliders are mathematical volumes and do not represent surface nets. They do not have backfaces as angrypenguin explained. A meshcollider is not a primitive collider. Note that the collider has nothing to do with the visual representation of an object. So the only relevant thing we have to talk about is the used collider.

    Also note that convex mesh colliders "may" also not have backfaces as a convex mesh collider also represents a complex volume that is bounded by infinite mathematical planes instead of a pure triangle net. When you tick the "convex" checkbox PhysX will calculate a convex hull of the mesh which may be quite different from the original mesh.