0
\$\begingroup\$

I am currently trying to make a pen draw on a paint. I am searching for contact points on the paint but there is too much contact points than expected.

I'm not sure to properly understand how collisions are detected. Only one side of the cube touches the paint, but four points are returned and seem to correspond to each corner of the cube projected onto the plane.

 private void OnCollisionStay(Collision collision)
    {
        Debug.Log(collision.transform.tag);
        if (collision.transform.CompareTag("Paint"))
        {
            Debug.Log("Pen enter collision with paint");
            foreach (ContactPoint contact in collision.contacts)
            {
                Debug.Log(contact.thisCollider.transform.name + " " + contact.otherCollider.transform.name);
                Debug.DrawRay(contact.point, contact.normal, Color.white);
            }
        }
    }

Only one side of the cube touches the paint, but four points are returned and seem to correspond to each corner of the cube projected onto the plane.

\$\endgroup\$
1
  • \$\begingroup\$ I'm actually getting the same! Also using OnCollisionStay(Collision collision) and the editor's Physics Debugger is showing me 2 contact points, but collision.GetContacts() is reporting only 1. Maybe it's a bug? I'm on 2022.3.8f1. \$\endgroup\$
    – FanManPro
    Commented Nov 24, 2023 at 1:16

1 Answer 1

1
\$\begingroup\$

What ended up being my issue is that OnCollisionStay() can call multiple times per FixedUpdate. It actually calls per collision. So my collider had two collisions, making my contact point counter incorrect.

Considering that, it also means if you store your contacts/GetContacts() outside of the OnCollisionStay() function, it will also get overwritten.

So the basic rule here is to not populate variables with GetContacts() outside of the scope of OnCollisionStay. Instead keep those variables local, and aggregate them manually if you need them in a different public scope.

[RequireComponent(typeof(Collider))]
public class CharacterColliderData2 : MonoBehaviour {
    public ContactPoint[] ContactPointsAggregated = new ContactPoint[8];

    // to avoid allocation
    private ContactPoint[] contactPoints = new ContactPoint[4];
    public int contactPointCount = 0;

    private void OnEnable() {
        contactPoints = new ContactPoint[4];
        contactPointCount = 0;
    }

    private void FixedUpdate() {
        contactPointCount = 0;
        ContactPointsAggregated = new ContactPoint[8];
    }

    // can run many times before FixedUpdate calls again
    private void OnCollisionStay(Collision collisionInfo) {
        int startingCount = contactPointCount;
        int collisionContactPointCount = collisionInfo.GetContacts(contactPoints);
        contactPointCount += collisionContactPointCount;

        for (int i = 0; i < collisionContactPointCount; i++) {
            ContactPoint contactPoint = collisionInfo.GetContact(i);
            ContactPointsAggregated[startingCount + i] = contactPoint;
        }
    }
}
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .