Reputation: 94
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
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
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