Material Memory Leak

I’ve found that working with renderer.material in some cases will cause a memory leak. It will duplicate materials and fail to remove them, even if the parent object is destroyed. This leads to an ever increasing material count. I found the thread below that discusses some ways to handle this, but I’m not sure how best to apply this info.

Resources.UnloadUnusedAssets will to get rid of the cloned materials, but I’m not sure where or when to call it. It seems to slow the game down if I call it too often. Has anyone run into this issue and how did you handle it?

Here’s some code that will produce a material leak.

using UnityEngine;
using System.Collections;

public class RayScript : MonoBehaviour {

public Color color1 = Color.red;
public Color color2 = Color.blue;
public float duration = 3.0f;

// Use this for initialization
void Start () {
	renderer.material.SetColor("_TintColor", color1);
            Destroy(gameObject, duration);
}

// Update is called once per frame
void Update () {
	
	float lerper = Mathf.PingPong(Time.time, duration) / duration;
	Color newColor = Color.Lerp(color1, color2, lerper);
	renderer.material.SetColor("_TintColor", newColor);


}

}

What you’re experiencing is intended behavior.
Every call to renderer.material will create a new material instance bound to that renderer. That is so you can modify material attributes without affecting the attributes on other renderers using the same material.

You can clean up the materials explicitly using Resources.Unload( renderer.material ) when done, instead of using Resources.UnloadUnusedAssets, which should be faster.

Either way loading and unloading resources is a relatively expensive operation.

If in your use case you can share attributes between renderers, you can use renderer.sharedMaterial, which will not create new instances but rather update the attributes on the material shared by all renderers.