Osuka42
Osuka42

Reputation: 94

How can I change the color of a material in Unity?

I'am developing a Vuforia app that uses Virtual Buttons. I used the example of virtual buttons and I found this part on the script

public void OnButtonPressed(VirtualButtonBehaviour vb)
{
    Debug.Log("OnButtonPressed");

    if (!IsValid())
    {
        return;
    }

    // Add the material corresponding to this virtual button
    // to the active material list:
    switch (vb.VirtualButtonName)
    {
        case "red":
            mActiveMaterials.Add(m_TeapotMaterials[0]);
            break;

        case "blue":
            mActiveMaterials.Add(m_TeapotMaterials[1]);
            break;

        case "yellow":
            mActiveMaterials.Add(m_TeapotMaterials[2]);
            break;

        case "green":
            mActiveMaterials.Add(m_TeapotMaterials[3]);
            break;
    }

    // Apply the new material:
    if (mActiveMaterials.Count > 0)
        mTeapot.renderer.material = mActiveMaterials[mActiveMaterials.Count - 1];
}

As is seen, I just must add the code at each case to 'do something'. Well, the thing I want to do is to change the color of an object. The object is a fbx exported from Maya and has an animation. I want to change the color of a mesh inside the object. The object is called "path", inside it has 3 meshes (polySurface1_MeshPart0, ..1, ..2), and each mesh has different materials corresponding to different parts of the mesh, they are materials without texture, just a solid color with shader diffuse. I need to change the color of one of these materials in a specific mesh of the object :)

Any help is highly appreciated.

Upvotes: 2

Views: 17413

Answers (2)

zambari
zambari

Reputation: 5035

First off, gameObject.renderer has been depreciated a long time ago, you should be using GetComponent() explicitly.

Secondly, you are adding to mActiveMaterials (which I assume to be a List or equivalent), but you don't seem to be clearing that list, whlist the code might work fine, you are creating a serious memory leak this way (unless you clear the list elsewhere)

Now, for each mesh renderer, there's two ways to access the material, theres Material[] materials, and material, which is effectively an equivalent of (with the omission of array boundary check and null checks)

material { get { return material[0]; } set {material[0]=value;}}

For meshes with only 1 sub-mesh, only material[0] is used, but for meshes with submaterials (it depends how models were imported, sometimes they get split into seperate single-material objects, and sometimes you get a single mesh with multiple materials).

Now I am not sure i understeand the reason behind adding a new material to the list, than only ever using the last material from the list (the list makes sense if you are working with multiple sub-meshes)

I would suggest something along the lines of

void Start()
{
    teapotRenderer=mTeapot.GetComponent<MeshRenderer>():
}

Material FindMaterial(string buttonName)
{
     switch (buttonName)
        {
            case "red":    return m_TeapotMaterials[0];
            case "blue":   return m_TeapotMaterials[1];
            case "yellow": return m_TeapotMaterials[2];
            case "green":  return m_TeapotMaterials[3];
            default:       return mdefaultMaterial;
        }

}

public void OnButtonPressed(VirtualButtonBehaviour vb)
    {
      mTeapotRenderer.material=FindMaterial(vb.VirtualButtonName);
    }

Upvotes: 0

Nestor Ledon
Nestor Ledon

Reputation: 1992

From the Unity3D Documentation: http://docs.unity3d.com/Documentation/ScriptReference/Material-color.html

You would need to either find the GameObjects at run time via GameObject.Find() or assign them to your scripts public members. Each mesh should be retrievable as a GameObject. Once you have reference to the GameObject in question you should be able to access it's material like so:

myGameObject.renderer.material.color = Color.Red;

An example using the code provided would be:

switch (vb.VirtualButtonName)
{
    case "red":
        mActiveMaterials.Add(m_TeapotMaterials[0]);
        GameObject go = GameObject.Find("The Name Of The Object You Are Looking For");
        go.renderer.material.color = Color.Red;
        break;
}

Upvotes: 1

Related Questions