Search Unity

Sweep Tests vs.MeshColliders - the horror.

Discussion in 'Physics' started by Bezzy, Jul 14, 2016.

  1. Bezzy

    Bezzy

    Joined:
    Apr 1, 2009
    Posts:
    75
    Hi. I just wanted to start this thread as a discussion of what's up with sweep tests?

    I've been using unity for 8 years, and in all that time I've found Physics.SphereCast, Physics.CapsuleCast, and rigidbody.SweepTest are all pretty untrustworthy, or a huge amount of work to use. I'm not quite pulling my hair out just yet, but I'm certainly in the mood to write one of those forum posts where you end up hitting backspace a lot to remove the complainey tone.

    I'm finding that they're
    a)very work intensive - I have to keep making work-arounds for floating point inaccuracy

    Try this with a convex meshcollider and a rigidbody, testing against a concave mesh collider:

    public Vector3 dir;

    ...
    void FixedUpdate()
    {
    RaycastHit info;
    if(rigidbody.SweepTest(dir, out info, distance))//do a sweep test in some direction.
    {

    rigidbody.position = rigidbody.position + dir*info.distance;//update rigidbody position so we can trace again from the end of the trace
    if(rigidbody.SweepTest(dir, out info, distance))//do a sweep test in the same direction, from the point at which the last trace ended
    {
    Vector3 secondTraceEndPoint = rigidbody.position + dir*info.distance; //this SHOULD

    //check if the vectors are the not same - they totally ought to be!
    if((secondTraceEndPoint - rigidbody.position).magnitude > float.Epsilon)
    {
    Debug.LogError("Followup swept trace went through the object, despite it casting from the end position returned by the initial trace");​
    }​
    }​
    }​
    }​
    The solution to this is to place the rigidbody.position for the subsequent trace a little bit back from the surface hit, either using the info.normal, or the initial trace dir.

    Not only do you have to do that, but then you have to worry about the step-back displacement away from the surface setting up your trace start position to be placed inside an opposite facing wall - and if that's part of the same mesh, your next trace against the mesh will be totally ignored.

    How much should you move it back by? God knows. In my experience it sometimes has to be as much as 0.02 units.

    0.02 units is 2 centimeters if you're sticking to proper scales! So, to have safe collision, nothing in your game should be closer than 2 centimeter to anything that it needs to touch with. That's not even close enough to worry about stuff Z fighting!



    b)often inaccurate - above and beyond the scope of floating point inaccuracy

    I've made sure that any meshes I'm using are triangulated out (because RaycastHit's triangleIndex is incredibly hard to use if your mesh has any quads in) but I notice that on very large triangles (long stretched out ones), the swept casts will really jitter a LOT - even if I've got a stationary rigidbody just casting out a SweepTest every frame, I might get different results back for each frame - when nothing in the scene has been updated to move at all, and where every rigidbody is kinematic! Where is this noise coming from?

    Like, I'm trying to do a swept trace a small distance to the ground, to check if I am in a grounded state, and it sometimes just manages to penetrate, even though I'm pulling my object back along the trace to make room for floating point error. And sometimes, doing /that/ means that the trace starts inside a wall, so the trace is ignored, and my thing thinks it's falling and through the floor.

    The only work around I can think of is to subdivide large triangles - this feels really crazy to have to do unless I'm missing something? It



    -------

    Ultimately, the calls feel untrustworthy. And I think I've been running into this problem since I started with unity 8 years ago. Will it ever be addressed? Can't this just be better? Am I just being a big baby, or has anyone else hit this kind of issue?

    When using IdTech, you could just do an AABB test anywhere you liked, and it'd come back with its final position, rock solid. There was never any chance it'd be microscopically inside another surface. If you subsequently traced from that position, it wouldn't count as being inside. I guess that was using a BSP system... ?



     
    Last edited: Jul 14, 2016
  2. GuardHei

    GuardHei

    Joined:
    Feb 10, 2018
    Posts:
    89
    What a great thread! So sad it is dead now.