I gave myself a headache a few weeks ago trying to modify a gameObject’s material and thought I had figured out the issue, but I ran into the same problem today.
When you try to modify an object’s material and run a test against it, the editor completely forbids you from doing so. This is because it might cause… MEMORY LEAKS IN THE EDITOR !!! (GASP) :( and shortly thereafter, the end of all life as we know it. It’s definitely impossible to either have Unity clean this up or give the user a WARNING instead of an error and allow them to clean it up manually.
And since it’s explicitly forbidden, we should issue an error message that sounds like a warning and suggests that it ISN’T explicitly forbidden:
[Error] 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.
How is it not bad practice to expose a variable to changes through scripting in a game context, but not in the editor context? How am I to test the functionality in the game if I can’t run tests in the editor? Why is material even exposed if it’s so dangerous to the editor? Is there any legitimate case for modifying material?
Oh, right, I’m supposed to use sharedMaterial. Well that sounds good, but here’s the problem: I don’t want to use a material which is shared between multiple objects. I want to create a new instance of this object and refer to its material, and not to the material on other instances of the object.
… what? SharedMaterial ISN’T shared between multiple objects, or even multiple instances of the same object? It actually refers to a single new material on a new object, and will not be shared unless I explicitly pass it around? Shouldn’t it then be called SHAREABLE material? Don’t almost all objects have the property of potentially being assigned to multiple objects by reference, and if so does that mean we have to rename EVERYTHING IN UNITY to have the prefix “shared”?
If this thing can do everything that I want ‘material’ to do, why not just call this thing ‘material’ and delete the old ‘material’ which is somehow mysteriously impossible to clean up after in the editor context? I guess naming objects based on their intrinsic qualities, and not qualities which they might possess if and only if new qualities are explicitly added, is passé.
All of this has the feel of being a messy, patchy, poorly considered solution to some deep engineering problem that I don’t have knowledge of. Quite possibly I am a complete idiot. I find it hard to believe that this can’t be done better, or at LEAST that ‘sharedMaterial’ can’t be given a better name.
All I want to do is get the specific material that actually exists on an object. I don’t want to risk altering random materials on other objects because I have to address a material that’s shared between multiple objects. If the object doesn’t exist and needs to be instantiated for a test, surely Unity should instantiate the entire object INCLUDING A NEW MATERIAL and then delete it after the test, again INCLUDING THE INSTANTIATED MATERIAL so it doesn’t leak. I don’t understand why this is difficult.