.material
and .materials
are getters that, when first used, create a new per-instance clone of the material(s) to assign and return.
This lets a beginner write code that looks correct:
GetComponent<Renderer>.material.color = Color.Blue;
...and have the result be that only the one object they ran this code on turns blue, instead of the perplexing result that ALL objects using the same material turn blue.
But for a case like yours, this on-demand instantiation is working against you. Once a clone of myMaterial
gets instantiated, it's no longer exactly equal to myMaterial
and gets a different name, making it harder to compare for equality.
For these more advanced cases, you can use .sharedMaterial
and .sharedMaterials
, which do not perform this automatic instantiation under the hood.
// Assign this in the Inspector instead of using Resources.Load().
// This is faster, and helps keep your build leaner.
[SerializeField]
private Material myMaterial;
private void addMaterial(GameObject gameObject) {
// Fetch renderer only once - don't repeat work unnecessarily.
if (!gameObject.TryGetComponent(out Renderer renderer)) {
Debug.LogError($"Game object {gameObject.name} does not have a Renderer.");
return;
}
// Similarly, fetch materials only once.
var oldMaterials = renderer.sharedMaterials;
var newMaterials = new Material[oldMaterials.Length + 1];
oldMaterials.CopyTo(newMaterials,0);
newMaterials[oldMaterials.Length] = myMaterial;
renderer.sharedMaterials = newMaterials;
}
Now, you can write code that checks for your material by reference equality:
private bool HasMyMaterial(GameObject gameObject) {
if (!gameObject.TryGetComponent(out Renderer renderer)) {
Debug.LogError($"Game object {gameObject.name} does not have a Renderer.");
return false;
}
return System.Array.IndexOf(renderer.sharedMaterials, myMaterial) >= 0;
}
As long as we're not instantiating a clone of the material anywhere, the instance we put into the array is the same instance we read back, so this reference equality trick works.
If you need to instantiate a copy of the material somewhere, well.. first, try not to. See if you can use MaterialPropertyBlock
instead. But if you must, then you'll need to record that new instance somewhere to check for it. We'd need to see more of your code / use case to advise how exactly to do that in a way that fits your game.