2D Collisions Are Totally Rubbish In 5.3

Toodles, o/

So, the 2D physics collision detection in 5.3 is a massive downgrade from 5.0. I have everything set to maximum (No Interpolation, Never Sleep, and Continuous Detection), but my OnCollisionEnter2D still doesn’t get called at medium to high impact velocities.

It’s not a bug in my script, because it’s debugging fine at low speeds. It’s to do with the collision detection. Has anything changed in 5.3 regarding physics quality?

Any help would be much appreciated.

Despite your obvious frustration, there’s no downgrade from 5.0 to 5.3 in 2D collision detection nor are there any major differences.

Continuous collision detection is rock solid but it’s only useful if you’re not modifying colliders or their transforms directly. Interpolation and sleeping have nothing to do with collision detection whatsoever.

Actually, turning sleeping off does help: When the moveable objects are sitting in a trigger collider and aren’t moving, the sleep mode doesn’t call OnTriggerStay2D. Setting the object’s Rigidbodies to never sleep allows the trigger to constantly call OnTriggerStay2D, regardless of the object’s velocity.

I think I managed to figure out a way around the slow initial collision, though. Basically I… Well, I kinda build my own OnTriggerEnter2D, using a dual array of internal Rigidbodies and booleans.

Thanks for getting back, though. [:)]

Still, sleeping has no effect on collision detection whatsoever. The OnStay callback is just something Unity pushes out based on a contact still in effect.

There is no continuous collision detection against triggers, there can’t be. Continuous detection allows the movement to a new position (which may be completely past another collider) but it calculates the impact point from the old position to this new position and places the body there. Because nothign actually collides with triggers, this process cannot happen.

Not sure what the ‘slow initial collision’ means either. This sounds like you’re simply moving completely past the trigger at speed and when it doesn’t overlap during an update, you don’t get a trigger callback (because it never happened from the physics system pov).

Your solution sounds a bit strange. It would be helpful if you explained what your actually trying to accomplish here. I’d suspect using something like CircleCastAll instead might work way better.

I need to call a function when the player initially collides with another certain collider. OnColliderEnter2D doesn’t work, because as soon as the physics decide to update, the colliders have already “bounced” away from each other. No amount of tweaking seems to change the collision update speed, it “quality”.

I still don’t fully understand what you’re trying to do, but I think the problem here is that OnColliderEnter2D is only called once at the start of the current collision. So It’s not that the detection is too slow, but rather that there is no detection happening for the other colliders at all.

All rigid bodies are updated at the same time too, so it’s impossible for an object to bounce off something between physics updates. However, they can sometimes miss collisions and pass-through thin objects completely when moving extremely fast.

One way to fix your problem might be to cast after the collision.

    public string collisionTag = "Untagged";
    public LayerMask castMask = -1;
    public float castRadius = 1f;


    void OnCollisionEnter2D(Collision2D coll)
    {
        if(coll.gameObject.CompareTag(collisionTag))
        {
            MyMethod();
        }
    }


    void MyMethod()
    {
        Collider2D[] colliders = Physics2D.OverlapCircleAll(transform.position, castRadius, castMask);

        if (colliders.Length > 0)
        {
            foreach (var c in colliders)
            {
                var rb2d = c.GetComponent<Rigidbody2D>();
                // do something with the rigidbody here.
            }
        }
    }

Or you could maintain a list of objects the player has collided with:

public string collisionTag = "Untagged";

    private List<Rigidbody2D> bodies = new List<Rigidbody2D>();


    void OnCollisionEnter2D(Collision2D coll)
    {
        if (coll.gameObject.CompareTag(collisionTag))
        {
            MyMethod();
        }
        else
        {
            bodies.Add(coll.rigidbody);
        }  
    }


    void OnCollisionExit2D(Collision2D coll)
    {
        bodies.Remove(coll.rigidbody);
    }


    void MyMethod()
    {
        if (bodies.Count > 0)
        {
            foreach (var rb2d in bodies)
            {
                // do something with the rigidbody here.
            }
        }
    }
1 Like