Lots of GC with barycentricCoordinate Smoothed Normals

Hi all,

I’m using the example code from the docs to get a smoothed normal from a raycast hit. It’s working well but building up a lot in the garbage collector. Any ideas how to tame that a little? I’m not sure I can cache the meshcollider as the raycast might hit another collider.

Any ideas?

Thanks,
Pete

void Update()
    {
        // Only if we hit something, do we continue
        RaycastHit hit;


        if (!Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hit))
        {
            return;
        }

        // Just in case, also make sure the collider also has a renderer
        // material and texture
        MeshCollider meshCollider = hit.collider as MeshCollider;
        if (meshCollider == null || meshCollider.sharedMesh == null)
        {
            return;
        }

        Mesh mesh = meshCollider.sharedMesh;
        Vector3[] normals = mesh.normals;
        int[] triangles = mesh.triangles;

        // Extract local space normals of the triangle we hit
        Vector3 n0 = normals[triangles[hit.triangleIndex * 3 + 0]];
        Vector3 n1 = normals[triangles[hit.triangleIndex * 3 + 1]];
        Vector3 n2 = normals[triangles[hit.triangleIndex * 3 + 2]];

        // interpolate using the barycentric coordinate of the hitpoint
        Vector3 baryCenter = hit.barycentricCoordinate;

        // Use barycentric coordinate to interpolate normal
        Vector3 interpolatedNormal = n0 * baryCenter.x + n1 * baryCenter.y + n2 * baryCenter.z;
        // normalize the interpolated normal
        interpolatedNormal = interpolatedNormal.normalized;

        // Transform local space normals to world space
        Transform hitTransform = hit.collider.transform;
        interpolatedNormal = hitTransform.TransformDirection(interpolatedNormal);

        // Display with Debug.DrawLine
        Debug.DrawRay(hit.point, interpolatedNormal);
    }

Lines 21 and 22 are each generating a fresh array from the data in the Mesh.

Just do it once or if they change in length perhaps??

Obviously “once” would have to be associated with a particular Mesh.

To add to above, use the GetX methods when it comes to mehes: https://docs.unity3d.com/ScriptReference/Mesh.GetVertices.html

Honestly the documentation would’ve answered your question. Have an already allocated list. This will save constant GC.

1 Like

Hey thanks @Kurt-Dekker ! I’m not sure I can guarantee it will be the same mesh though which is a bit of an issue. I found If I break the mesh up it’s way less obvious but then the issue of caching the array.
Hey Spiney thanks, I’ll check that out. My code from above was copied directly from the documentation by the way. :smile:

The docs also mention to use the advanced API if you need maximum performance when doing mesh operations.

2 Likes

Nice that all seems a lot happier, thanks!

1 Like