Unity Mesh Modification

As part of the technical preview for a project I’m working on I have ran into an interesting problem that I’m trying to solve. In Unity when you use the OnCollisionEnter/OnCollisionExit collision handling and need the information about the mesh it is colliding with.

Modifying the mesh requires knowledge of the triangles that you are interacting with; however OnCollisionEnter doesn’t give you this information, you need a RayCastHit to access this information. One way to get the RayCastHit is to perform a Physics.Raycast call based on the collision contacts. Once you have the RayCastHit you can use triangleIndex on that object to get the required information including the vertex information.

Going from the OnCollisionEnter collision contacts to a RayCastHit that gives you the correct information isn’t as simple as it should be. You have to get an offset point that is just behind the collision point, and then do the Raycast from there otherwise it detect the triangles further away and misses the one that it should be detecting. Below is the code that I used to get this all working.

private void OnCollisionEnter(Collision collision) {
    GameObject colGo = collision.collider.gameObject;
    points = collision.contacts;
    if (points.Length > 0) {
        for (int i = 0; i < points.Length; i++) {
            Vector3 offsetPoint = points[i].point - (points[i].normal + (Vector3.down * 1.1f));
            Debug.DrawRay(offsetPoint, points[i].normal, Color.blue);
            Debug.DrawRay(offsetPoint, -points[i].normal, Color.yellow);
            Debug.LogFormat("{0}-{1}=>{2}", points[i].point, points[i].normal, offsetPoint);
            if (Physics.Raycast(offsetPoint, -points[i].normal, out RaycastHit hit, Mathf.Infinity)) {
                Debug.LogFormat("{0}||{1}", points[i].point, hit.triangleIndex);
                if (hit.triangleIndex != -1) {
                    Mesh mesh = hit.collider.gameObject.GetComponent<MeshFilter>().sharedMesh;
                    Vector3[] verts = mesh.vertices;
                    int[] triangles = mesh.triangles;
                    Vector3 _a = hit.transform.TransformPoint(verts[triangles[hit.triangleIndex * 3]]);
                    Vector3 _b = hit.transform.TransformPoint(verts[triangles[hit.triangleIndex * 3 + 1]]);
                    Vector3 _c = hit.transform.TransformPoint(verts[triangles[hit.triangleIndex * 3 + 2]]);
                    Debug.LogFormat("{0}|{1}|{2}", _a, _b, _c);
                    Debug.DrawLine(_a, _b);
                    Debug.DrawLine(_b, _c);
                    Debug.DrawLine(_c, _a);
                }
            }
        }
    }
}