OnCollisionEnter2D being called upon exiting collider?

Obviously that shouldn’t happen but I don’t know what else to describe it as. I have a simple game where you can fling an object between two sides of the screen through the use of spring joints. I have box colliders set up on either side that when entered create a spring joint on the object connecting it to a rigidbody the collider is attached to (the spring joint is destroyed when the object reaches a certain velocity). The player is supposed to pull back the object and release it to fling it to the other side of the screen, I have adjusted the size of the colliders so that the object cannot be pulled back far enough to exit the collider without being flung so as not to accidentally retrigger the OnCollisionEnter event. However, sometimes, and not everytime, when the object exits one of the box colliders it will suddenly gain a spring joint attached to the same rigidbody it was just attached to, keeping it from reaching the other side of the screen. I have even tried setting it to ignore collisions with the collider that it last touched and this still happens. I have no idea why this is happening and would greatly appreciate any help that you guys could offer. The code is as follows…

Code attached to object:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BeeFling : MonoBehaviour {

public float maxstretch = 1.5f;
public LineRenderer left;
public LineRenderer right;
public Collider2D ToIgnore;
public bool ignore = true;

public Transform anchor;
private Rigidbody2D rb;
public SpringJoint2D spring;
bool OnTether = true;
bool ClickedOn = false;
public Ray mouseRay;
public Ray anchorToBee;
private Animator anim;
private float maxstretchsqr;
Vector3 prevVelocity;

void Awake()
{
    spring = GetComponent<SpringJoint2D>();
    rb = GetComponent<Rigidbody2D>();
    anim = GetComponent<Animator>();
    anchor = spring.connectedBody.transform;
}

void Start ()
{
    LineSetUp();
    mouseRay = new Ray(anchor.transform.position, Vector3.zero);
    anchorToBee = new Ray(anchor.transform.position, Vector3.zero);
    maxstretchsqr = maxstretch * maxstretch;
}

void Update ()
{

	if(ClickedOn)
    {
        Dragged();
        anim.SetBool("PulledBack", true);
    }

    if(spring != null)
    {
        if(!rb.isKinematic && prevVelocity.sqrMagnitude > rb.velocity.sqrMagnitude)
        {
            Destroy(spring);
            rb.velocity = prevVelocity;

            anim.SetBool("PulledBack", false);
            anim.SetBool("Flying", true);

        }

        if(!ClickedOn)
        {
            prevVelocity = rb.velocity;
        }

        renderUpdate();
    }
    else
    {
        left.enabled = false;
        right.enabled = false;
    }

}
void OnMouseDown()
{
    spring.enabled = false;
    ClickedOn = true;
}

void OnMouseUp()
{
    spring.enabled = true;
    rb.isKinematic = false;
    ClickedOn = false;
}

public void LineSetUp()
{
    left.SetPosition(0, left.transform.position);
    right.SetPosition(0, right.transform.position);

    left.sortingLayerName = "Foreground";
    right.sortingLayerName = "Foreground";

    left.sortingOrder = 7;
    right.sortingOrder = 7;
}

void Dragged()
{
    Vector3 mousePoint = Camera.main.ScreenToWorldPoint(Input.mousePosition);
    Vector2 anchortomouse = mousePoint - anchor.transform.position;

    if(anchortomouse.sqrMagnitude > maxstretchsqr)
    {
        mouseRay.direction = anchortomouse;
        mousePoint = mouseRay.GetPoint(maxstretch);
    }

    mousePoint.z = 0;
    transform.position = mousePoint;
}

void renderUpdate()
{
    Vector2 beetoanchor = transform.position - anchor.transform.position;
    anchorToBee.direction = beetoanchor;

    Vector3 holdpoint = anchorToBee.GetPoint(beetoanchor.magnitude);

    left.SetPosition(1, holdpoint);
    right.SetPosition(1, holdpoint);
}

private void OnCollisionEnter2D(Collision2D collision)
{
    Physics2D.IgnoreCollision(ToIgnore, GetComponent<Collider2D>(), ignore);
}

private void OnCollisionExit2D(Collision2D collision)
{
    Debug.Log("Called");
    Physics2D.IgnoreCollision(ToIgnore, GetComponent<Collider2D>(), false);
}

}

code attached to box colliders:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class AnchorController : MonoBehaviour {

public GameObject bee;
public LineRenderer left;
public LineRenderer right;

private Rigidbody2D rb;
private Rigidbody2D beerb;
private Animator anim;
private SpringJoint2D spring;
Collider2D ignore;
bool hasjoint = false;

private void Start()
{
        anim = bee.GetComponent<Animator>();
        beerb = bee.GetComponent<Rigidbody2D>();
        rb = GetComponent<Rigidbody2D>();
        ignore = GetComponent<Collider2D>();

}

private void OnCollisionEnter2D(Collision2D other)
{
    if(other.gameObject.name == "Bee")
    {
        Vector3 contact = other.contacts[0].point;
        BeeFling fling = bee.GetComponent<BeeFling>();

        fling.ignore = false;
        fling.ToIgnore = ignore;
        fling.ignore = true;

        beerb.velocity = Vector2.zero;
        beerb.angularVelocity = 0f;

        Vector2 newpos = new Vector2(contact.x, transform.position.y);
        transform.position = newpos;

       // fling.spring = bee.GetComponent<SpringJoint2D>();

        if (fling.spring == null)
        {
            Debug.Log("Adding joint");
            other.gameObject.AddComponent<SpringJoint2D>();
            spring = bee.GetComponent<SpringJoint2D>();
            hasjoint = true;
        }

        beerb.isKinematic = true;
        spring.connectedBody = rb;
        spring.frequency = 5;
        spring.autoConfigureDistance = false;
        spring.distance = .005f;
        anim.SetBool("Flying", false);
        fling.right = right;
        fling.left = left;
        fling.LineSetUp();

        fling.anchor = rb.transform;

        fling.mouseRay = new Ray(fling.anchor.transform.position, Vector3.zero);
        fling.anchorToBee = new Ray(fling.anchor.transform.position, Vector3.zero);

        fling.spring = spring;
    }
}

private void OnTriggerExit2D(Collider2D collision)
{
    hasjoint = false;
}

}

@oars I realize it’s been awhile, but maybe this will help. I had a similar problem recently in a 2D platformer I’m working on. OnCollisionEnter was being called on tiles that I was actually exiting as I walked across a surface made up of several tiles side-by-side.


The fix for me was to go into the Physics2D settings and lower the “Default Contact Offset” property, which was introduced in 2017.1. From the documentation: “Contact offset allows the collision detection system to predictively enforce the contact constraint even when the objects are slightly separated.”


Here’s the link to the documentation, for brevity’s sake.