- Home /
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.
http://answers.unity3d.com/questions/192561/renderermaterials-leaking-materials.html
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);
}
}
Answer by MartinCA · Oct 04, 2013 at 09:03 AM
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.
Thanks for the great info. Using renderer.shared$$anonymous$$aterial did indeed solve the issue I was seeing. In my use case, effect is slightly different as now all the lines lerp simultaneously rather than on their own individual timers, but I think I understand why this is now.
Also, I found the following: http://docs.unity3d.com/Documentation/ScriptReference/Renderer-material.html
By adding this code to my use case, I was able to specifically destroy the cloned material:
void OnDestroy() { DestroyImmediate(renderer.material); }
@toborifc, please accept this answer so this question could be closed.
Thanks! We had a similar problem in $$anonymous$$asters of Conquest what cause our server memory to be completely used up. This fix did the trick.
Your answer
Follow this Question
Related Questions
Creating a MemoryStream from WWW.bytes leaks memory 1 Answer
Unity WebGL build memory discrepancy in local hosted and web hosted 0 Answers
Prefab instantiation and destruction 3 Answers
Unity in embedded QWidget memory problem 0 Answers
Unity full memory crash, during AssetDatabase.LoadAssetAtPath 0 Answers