Correcting for a collision overlapping too much?

I have a TileMap with a TileMapCollider2D and a Sprite with a BoxCollider2D. I’m not using physics at all so I’m correcting for the collision on my own. Here’s my attempt:

void FixedUpdate() {
    float h = Input.GetAxis("Horizontal") * Time.deltaTime * this.Speed;
    float v = Input.GetAxis("Vertical") * Time.deltaTime * this.Speed;
    Vector3 pos = this.transform.position;
    pos.x += h;
    pos.y += v;

    foreach (Tilemap map in this.Maps) {
        TilemapCollider2D mapc = map.GetComponent<TilemapCollider2D>();
        ColliderDistance2D dist = this.boxCollider.Distance(mapc);
        if (dist.isOverlapped && dist.isValid) {
            Debug.DrawLine(dist.pointB, dist.pointA, Color.white);
            Vector2 correction = dist.normal * dist.distance;
            pos += (Vector3)(correction);
        }
    }

    this.transform.position = pos;
}

This logic is on the blue square in this gif:

108127-correction.gif

According to the documentation, dist.normal * dist.distance should be exactly the distance and direction required to make the two colliders touch. However you can see that I can push a few pixels into the red walls. When I release the button it takes several frames to back out of the wall. It goes a little haywire too when I go diagonally into the corner.

TLDR: Insert this.transform.position = pos; at line 17 (just before the foreach loop).


When i had such problems it always was code reordering issue. To me it looks like it is because you are adding to the pos vector and applying it as current position at the end. But you are calculating the collision according to boxCollider’s last/previouse frame (i.e. h and v are not taken into account) . In other words your collision check is one frame late - you check if there was collision last frame and apply the movement after that.

You should apply pos as transform.position before calculating ColliderDistance2D (or find a way to check against pos itself).

I had this problem too with a game I was designing. I’m looking forward to seeing the answer to this one , because I fixed it with a not so elegant approach. But I’m pretty sure it has something to do with how the physics components are interacting with each other. When you add force to the collider it keeps pushing towards the other collider that’s why you have that little overlap with a reversed force. In the corner you get the haywire because now the opposite force is pushing back from two directions.
Hope this helps lol, but thanks for asking the solution will help me out as well :).

Long shot answer attempt:

Usually Distances formulas are usually from centers of the transforms, meaning approaching at non-perpendicular angles produce different distances.

I think you may want something to do with Bounds properties of the colliders instead.

I’ve only used physics so far, and haven’t done this personally, but I think a few of the Bounds functions look useful. My thinking is the Intersects / ClosestPoint in combination (if the objects bounds intersects the wall’s boundes, adjust the objects closest point to

It’s happening because the player is trying to force its way into the collider on that frame and on the next frame collision is detected and the player is pushed back.
I have a not so elegant solution.

when the player hits the “red walls” using “uparrow” for example. just take away user’s ability to press “uparrow” anymore, using boolean variables and OnCollisionStay2D() function
and OnCollisionExit2D() give back control.
I have never tried it though. I am suffering from the same problem, but left it as it is.


For now, I’ve added a RigidBody2D and tweaked some of the Project Settings for Physics2D until I have what I want. It still presses into the walls but not nearly as much as before. You can’t notice it. Also, because of the slight pressing into walls, I’ve given the BoxCollider2D a smaller size and a radius. The rounded corners prevent it from catching on walls that are flush with each other.

108174-rigidbody-correction.gif

I didn’t realize that a rigid body would reject collisions even if I’m not applying forces. This may not be the optimal solution since it’s using the physics engine to achieve the push back but it’s getting me the results I’m after. I’ll over-optimize later if this has a noticeable impact on performance.