I was trying to change the transparency of a Button object. I tried a few things like:

  • button.GetComponent<Renderer>().material.color = translucentColor
  • button.GetComponent<CanvasGroup)().alpha = 0.5f

And a few other things, I'm not sure. But the weirdest thing happened. I changed some value of something to like half alpha, and suddenly, every UI element in my game is permanently translucent! Even though I reverted that code, I can't figure out what has turned permanently translucent.

Is there some sort of god object attached to the canvas whos properties can be changed at run time and then set forever? I'm a bit new to Unity so seeing this behavior is very unnerving and weird.

I'm poking around in Unity's editor UI and I see something called the Default UI Material at white at half transparency. Could that be it?

If so, is that changeable? It's all grayed out.

  • \$\begingroup\$ Almost certainly that material. Unchangeable though? Bug? Can you try to change it back, programmatically? \$\endgroup\$ – Engineer Aug 2 '17 at 4:42

This sounds like a bug or oversight in Unity.

Normally a line like this:

someObject.GetComponent<Renderer>().material ...

will create a copy of the current material being used, unique to this object, specifically so that whatever you do to the material next won't spill over onto other objects sharing that material, or alter the source asset in your project files.

(You can use the .sharedMaterial property instead to avoid this copy if you're being careful and want to control how many material copies get instantiated)

Unfortunately, the .material property on UI renderables like Image does not have this copy behaviour.

So this:

someObject.GetComponent<Image>().material ...

hands you the actual original source material the object is currently using, without copying it.

And if you didn't set a custom material on the UI, then this gives you a reference to the global default UI material and lets you change it in code, even though it's treated as non-editable in the editor interface. It seems like mucking with this should at least generate a warning.

Fortunately, changing the material directly is not the preferred way to apply colour changes to UI (which might be why this seeming inconsistency slipped through). Instead, most UI renderables expose colour properties for this purpose, which can apply tints on top of the material colour, letting us draw lots of differently-coloured UI in batches without lots of costly material changes.

So you'd do something like:

myButton.GetComponentInChildren<Image>().color = translucentColor;

That way you tint just the button's backing image, not everything in the UI!

To fix the default UI material, all I had to do was close my project and re-open it. It seems Unity doesn't serialize changes to the default UI material (fortunately!)

  • \$\begingroup\$ I think you're right, I must have reached too deep and modified the default material. Also you're totally right about the last part, this reset itself upon re-opening Unity. Thanks! \$\endgroup\$ – Keith Aug 3 '17 at 16:31

Each component type in your envoironment should have a different material. Therefore, if you want to change the transparency of the button, it won't change the transparency of other objects.

  • 1
    \$\begingroup\$ This is actually not an ideal way to create this behaviour. The extra materials prevent the different UI elements from being drawn together in big batches, which can impact performance. Instead, Unity lets us choose tint colours item-by-item in a much more lightweight way (using vertex colours under the hood) so we don't need the overhead of extra material instances. \$\endgroup\$ – DMGregory Aug 2 '17 at 23:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.