I have a prefab that I am using for spawning several objects in my game. These objects are not dynamically created, but rather placed in the scene by hand. These objects need to dynamically change colour individually, and thus I can’t use the ‘sharedMaterial’ property of the renderer from the onset, as that would change all objects that use that material. So I am using the regular ‘material’ property to clone a copy and use that.
As I’ve read in the Unity docs, when creating material instances, you are responsible for destroying them after you are finished using them. There is example code in the docs that I adopted, and is supposedly the correct way to dispose of instanced materials.
My relevant code below:
void Start()
{
// Find the object in our local hierarchy that has the renderer component
perchMeshRenderer = transform.FindChild("Perch Mesh").renderer;
// Save the reference to our original material
originalMaterial = perchMeshRenderer.sharedMaterial;
// Copy the material so we can alter it per-object
perchMaterialInst = perchMeshRenderer.material;
perchMeshRenderer.sharedMaterial.SetColor("_Color", neutralMainColour);
perchMeshRenderer.sharedMaterial.SetColor("_RimColor", neutralRimColour);
captureLight.color = neutral;
nestRef = GameObject.Find("Nest").GetComponent<HQ>();
nexusRef = GameObject.Find("Nexus").GetComponent<HQ>();
lifeAmount = startingLife;
}
void OnDestroy()
{
Debug.Log("Instanced Material Before Destroy: " + perchMaterialInst);
DestroyImmediate(perchMaterialInst, true);
Debug.Log("Instanced Material After Destroy: " + perchMaterialInst);
Debug.Log("Original Material: " + originalMaterial);
perchMeshRenderer.sharedMaterial = originalMaterial;
Debug.Log("New shared material on renderer: " + perchMeshRenderer.sharedMaterial);
}
Now, on my destroy function, I have a bunch of Debug tests to see what is actually going on when this object gets destroyed. The readout is as follows:
-
Instanced Material Before Destroy:
Perch_Mat (Instance)
(UnityEngine.Material) -
Instanced Material After Destroy:
null -
Original Material: Perch_Mat
(UnityEngine.Material) -
New shared material on renderer:
Perch_Mat (UnityEngine.Material)
So based on what the logs say, the code seems to have worked. However, I still get an error message that states: “Instantiating material due to calling renderer.material during edit mode. This will leak materials into the scene. You most likely want to use renderer.sharedMaterial instead.” And sure enough, when I select the mesh of the object (not when running, but while in the editor), the material it is using is named “Perch_Mat (Instance)”, even though I just deleted the instance, and set the material back to the original.
Worse yet, a new ‘(Instance)’ gets appended to the material name every time I run the game. So after running the game 5 times, the material name becomes “Perch_Mat (Instance)(Instance)(Instance)(Instance)(Instance)”. This is definitely not desired behaviour, and totally not what I expected from my code. I’ve been looking around on both Unity Answers and elsewhere on the net, but apparently everyone else is having no problems deleting their material instances.
What am I doing wrong?