I have a simple set of cubes that I fade using the alpha property of the material’s color. As this changes the material asset, I noticed that the r, g and b values of the material’s color change, too, even though I never touch those. It even happens when I don’t fade. I suspect it is because of the following code, which I wrote to make sure the material is back to transparent when I stop playing. It’s called in OnDestroy():
Color tmp = myMaterial.color;
tmp.a = 0;
myMaterial.color = tmp;
The changes look like floating point precision errors (they are really small, 8th digit after the point or so). However, I would expect the values to stay the same when I do not touch them.
I know how to workaround this (for example by not changing the asset, only the instance), but I would like to understand what’s going on here.
Hmm, that’s an interesting read, but I don’t see how this could affect the color values. There is no conversion going on as far as I can tell, as I copy the Color object entirely. To note it in case it is relevant, my project uses linear color space.
Meanwhile, I tried something and (redundantly) manually copied r, g and b to tmp after creating tmp (between line 1 and 2). It did not help.
Also, the problem seems to occur every other time I play the project, not every time.
Linear color space means that colors will be converted from gamma space on the CPU side to linear colors on the GPU side. Now I have no idea how the color property has been implemented but could be implemented like this
public Color color
{
get { return GetColor("_Color").gamma; }
set { SetColor("_Color", value.linear); }
}
(it’s more likely that the conversion is within the SetColor, GetColor function but you get the idea).
So the getter wouldn’t return exactly what you set with the setter because of numerical errors.
Easy fix would be to store the color externally instead of calling the getter.
PS: Color is a struct, not a class. So it will be copied:
Well, that link shows that it has not been implemented like you suggested, which honestly would have shocked me a little. Color is indeed a Struct and hence my code is probably not guilty of changing any values as everything is just copied. So my guess is still that it’s rather a C# than a Unity problem and copying structs with floats somehow can lead to precision loss.
After investigating further, I figured out that the change must happen in Unity internal code. I only have one script that touches the material and the changes have already happened before that script ever runs. I can also see that the material file has changed right after the project start.