0
\$\begingroup\$

I have a compound GameObject that is made up of 5 sprites name dot1 till 5. I'd like to have a little script on the parent object that would allow me to change the colours of the child objects from the unity inspector. I want the colours to change directly in my scene without having to press play. This already happens when I would set the colours directly from the child objects. But I'd like to have the properties visible in my main object and set the colours from there.

So far I'm unable to make the changes visible in scene mode.

enter image description here [ExecuteInEditMode]

public class Chain : MonoBehaviour {

    public GameObject dot1;
    public GameObject dot2;
    public GameObject dot3;
    public GameObject dot4;
    public GameObject dot5;

    public Color Color1;
    public Color Color2;
    public Color Color3;
    public Color Color4;
    public Color Color5;

    void Start () {
    dot1.renderer.sharedMaterial.color = Color1;
    dot2.renderer.sharedMaterial.color = Color2;
    dot3.renderer.sharedMaterial.color = Color3;
    dot4.renderer.sharedMaterial.color = Color4;
    dot5.renderer.sharedMaterial.color = Color5;
    }

    void Update () {

    }
}
\$\endgroup\$
3
  • \$\begingroup\$ Not following. What's wrong with your current script? (Aside from messiness, which can be cleaned up later.) \$\endgroup\$
    – Evorlor
    Commented Feb 1, 2015 at 15:06
  • \$\begingroup\$ the changes don't happen in my scene. only when I've pressed the play button. \$\endgroup\$ Commented Feb 1, 2015 at 15:17
  • \$\begingroup\$ Ohhh I get it. I'm not sure how then. Check to see if there is something like Debug.Color(Blue); \$\endgroup\$
    – Evorlor
    Commented Feb 1, 2015 at 15:18

1 Answer 1

1
\$\begingroup\$

You can add a method like this:

#if UNITY_EDITOR
void OnValidate()
{
     if(dot1 != null && dot1.renderer != null)
         dot1.renderer.sharedMaterial.color = Color1;

     if(dot2...
}
#endif

The # lines ensure this function only compiles in editor builds.

OnValidate() is called in-editor anytime a value changes in the inspector. Because this includes when the script is first added to an object, and hasn't had all of its public fields populated yet, you need to be a little extra careful about checking for null values even in places that would never be null at runtime.

You can streamline this code if you replace the separate GameObject & Color fields for items 1-6 with a pair of Renderer[] and Color[] arrays - that way you can iterate over them instead of writing the same line 6 times, and Unity will enforce that whatever you put in the first array will have a Renderer component, saving a validation check in your code.

Note that changing the sharedMaterial's color will change the current material asset that each dot is referencing. That means if any two dots are sharing one material, whichever one gets its color set last will apply to both. If you're using version control, these material files will constantly show up as having been edited, because Unity detects that code has changed them anytime someone opens a scene with an instance of this script in it.

You can avoid this by creating a copy of the material before modifying it, but note that Unity doesn't garbage collect materials, so you'll need to manually destroy the copy when the script is deleted/unloaded, even in Editor (using DestroyImmediate) to keep duplicate materials from building up in memory.

\$\endgroup\$
0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .