- Home /
How do I change component properties without overriding them with parent component?
Hello, I'd like to write a script that works similar to setting alpha in CanvasGroup: https://docs.unity3d.com/Manual/class-CanvasGroup.html
When I set alpha in CanvasGroup, child objects opacity changes but doesn't get overwritten. I'd like to achieve similar effect for setting child SpriteRenderers tint color. Is it possible not to change their color property permanently? So the tint color would just depend on enabled parent component's value?
Answer by LeeroyLin · Jun 20, 2018 at 08:13 AM
You can change the material color, but notice that if you only change the color to your target color, the final color will be your target color * SpriteRenderer color. What you should do is use the target color RGB divided by the SpriteRenderer color RGB. I hope this will help you:
public bool isUseColor = true;
public Color col;
void Update () {
foreach (Transform item in transform)
{
Color c = item.GetComponent<SpriteRenderer>().color;
Color newCol = new Color();
newCol.r = col.r / c.r;
newCol.g = col.g / c.g;
newCol.b = col.b / c.b;
newCol.a = col.a / c.a;
item.GetComponent<Renderer>().material.color = isUseColor ? newCol : Color.white;
}
}
Hmmm, sprites in Unity share default sprite material. Won't your code affect other sprites? - the ones that aren't object's children.
Besides I need it to work in editor, so OnValidate() would be better than Update() :)
Well, it's great to use OnValidate(). And I find a way to change the material which will not affect other sprites by using "$$anonymous$$aterialPropertyBlock".
And there is another problem is that when original color's alpha value set to 0, the new color will be black. To solve this, I change the 0 alpha value to a very small value.
foreach (Transform item in root)
{
Color c = item.GetComponent<SpriteRenderer>().color;
if (c.a == 0) {
c.a = .004f;
item.GetComponent<SpriteRenderer>().color = c;
}
Color newCol = new Color();
newCol.r = color.r / c.r;
newCol.g = color.g / c.g;
newCol.b = color.b / c.b;
newCol.a = color.a / c.a;
$$anonymous$$aterialPropertyBlock b = new $$anonymous$$aterialPropertyBlock();
b.SetColor("_Color", newCol);
item.GetComponent<SpriteRenderer>().SetPropertyBlock(b);
}
Hope this can help you.
Thanks, it works! But it works strangely... When I change color in editor, sprite loses it's colors. The color is applied, when Unity window loses and regains focus ($$anonymous$$imize - maximize).
$$anonymous$$y previous code (changing sprite color property) worked on the fly:
SpriteRenderer[] sprites = GetComponentsInChildren<SpriteRenderer> (true);
for (int i = 0; i < sprites.Length;) {
sprites [i].color = tintColor;
}
But I don't like it because it makes colors of prefab instances "dirty".
It would be nice to know, how CanvasGroup actually works...