syntax for a finding a material by name in the array

I am new to Unity. I apologize for the stupid or obvious dumb question.

I need to set the color property of one material of the 18 on an imported object. I see from other posts that I need to take a copy of the renderer.material array, find the correct element of that, change the color.a property there, then assign the ENTIRE array to the renderer.material array. OK so far. The “find” part is my problem.

In the inspector, this is element number 2, called “BODY_Skin” actually. I am puzzled because diffuse materials, say, are described in the unity documentation as having “two properties, color and texture”, but that doesn’t include a NAME. Isn’t name a property? If not what is it?

So, I CAN iterate through the elements, but how am I supposed to figure out which of the elements in the array is the one named “BODY_Skin” ?

Surely the name is accessible somehow. Or do I just assume that element #2 as shown in the inspector will always be #2 and update that element of the array hoping it’s the one I want?

Again I apologize for the dumb question but I HAVE searched and I really cannot find in the manual or unityAnswers or on the web how to get at the NAME of a material.

GameObjects contain Components that define what they do in the game. The script that you added is an example of a Component. GameObjects that are visible will also have either a MeshRenderer Component or a SkinnedMeshRenderer Component, depending on how it was created. What you need to do is access that renderer Component, then set the alpha on the Material property of the renderer Component.

Luckily Unity makes this pretty simple to do, and you were already close. You might try something like:

renderer.material.color.a = 0.5f;

That line means you are modifying the material associated with the renderer component that is also on the same GameObject that this script is running on.

The tricky part is that you said your object has multiple materials, so the above code will only change the alpha of the first material… which may or may not be what you want. So, you’ll probably need to figure out the index of the “skin” material by looking at the list of materials. The first material is index 0, the second is 1, etc. Then, you would change (for example) the second material by typing this:

renderer.materials[ 1 ].color.a = 0.5f;

That’s it! And the simplest place to put that code is just in the Start( ) method of your script which should have been auto-created when you created the script. That way the script will execute as soon as you start your game.

OK, that works for my original question of how to set my specific case. (working code below). Thank you!

I still would like to get rid of the magic number and manual look up of the index and if someone knows what code snippet will take the name of the material as input and return the index in the array, I’d appreciate it.

– start of file –

#pragma strict

/*

  • Problem: game object has 18 different materials, we want to set color.a in just one of them
  • Punt: just looked in inspector to find the index of the one we want to set (2).
  • Written: January 14, 2012
  • Version: Unity 3.5 (developer beta)
  • Function: makes object translucent when p key is pressed,
  •        restores full opacity when s key is pressed.
    
  • Comment: Direct assignemnt of just one individual material array element IS successful
  •        (apparently in some prior version of Unity you had to modify a copy and then set the entire array)
    

*/

var myMaterials : Material ;
var materialIndex:int = 2; // magic number, looked up manually in the inspector for my special case

function Start () {
myMaterials = renderer.materials;
}

function Update()
{
if (Input.GetKeyDown (“p”))
{
myMaterials = renderer.materials;
renderer.materials[2].color.a =0.2;
}
if (Input.GetKeyDown (“s”))
{
renderer.materials[2].color.a =1.00;

}

}

– end of file –

OK, if you’re looking to index by name rather than number, you should try this:

foreach( Material m in renderer.materials ) {
    if ( m.name == "body" ) {
        m.color.a = 0.5f;
    }
}

I’m not at a computer with Unity so I can’t test the above code, but I’m pretty sure it would work.

It should be noted that this code is not as efficient as using a direct index because of all the string comparisons required to find the Material. It also bloats 1 line of code out to 5 (something I try to avoid if I can). But at that point we’re talking about programming style and best practices rather than merely making it work.

If the only reason for doing this is to avoid someone screwing things up later by changing the order of materials, you should consider that they can still screw things up by changing the name of the material.

You can’t possibly catch both error cases, so you really have to rely on someone to just be responsible about the material setup at some point. And I don’t think either error case is necessarily more likely than the other. So personally, I would tend to opt for efficiency in those cases. If I wanted it to be more readable I would just add a comment that index 5 corresponds to the “body” material.

But in all honesty, in this case, efficiency probably isn’t your biggest concern… so if you like the string comparison version, I’d say go for it.

Material’s name after start is “body (Instance)”

Material’s name after start is “body (Instance)”