Changing shaders for all children, some with multi-materials.

I’m trying to swap shader types at runtime of all children of a particular game object. The issue is that some of the children have multi-sub object materials and some do not. I’m using a snippet from the Unity scrip reference…

 function Update() {
var shader1 : Shader = Shader.Find( "Diffuse" );
var shader2 : Shader = Shader.Find( "Transparent/Diffuse" );


	for (var child : Transform in transform) {
	
		
		if( Input.GetButtonDown("Jump") ) {
		
		
			if( child.renderer.material.shader == shader1 ) {
				child.renderer.material.shader = shader2;
					}
						
			else	{
				child.renderer.material.shader = shader1;
			}
				}
			}
		}

This only affects the first material element in the array (if there is more than one element).

So I altered the code a bit in order to affect the materials like so…

			if( child.renderer.material.shader == shader1) {
			child.renderer.material.shader = shader2;
			if (child.renderer.materials[1]) {
				child.renderer.materials[1].shader = shader2; }
				else
					return;
					}
				
		else
			{
			child.renderer.material.shader = shader1;
				if (child.renderer.materials[1]) {
					child.renderer.materials[1].shader = shader1;
					}
					else
						return;

The issue here becomes that the script halts when the “array index is out of range” for objects that only have one material element. There is no crash, but objects below the trouble making object in the hierarchy are unaffected by the script.

I was hoping for a scripted solution that could work for objects with mutli-sub object materials and objects with single materials. Otherwise I’ll be going back into 3DS Max to make the meshes consistent regarding material(s).

Any help is appreciated!

First, check for input before doing anything, you are checking for the Jump button for each child, on each frame.

You need to recurse the tree. Make a separate function, like 'SetShaderRecursive (parent : Transform, shader). In that function you set the shader on the parent (assuming it has a renderer, you should check for that), then simply foreach child :Transform in Parent, call SetShaderRecursive (child, shader). That will walk the whole tree setting your shaders accordingly.

var shader1 : Shader;
var shader2 : Shader;
function Start(){
 shader1 = Shader.Find( "Diffuse" );
 shader2 = Shader.Find( "Transparent/Diffuse" );
}

function Update() {
  if( Input.GetButtonDown("Jump") )
    SetShaderRecursive (transform);
}

function SetShaderRecursive (parent : Transform){
  if (parent.renderer)
  {
    if (parent.renderer.material.shader == shader1 )
      parent.renderer.material.shader = shader2;
    else
      parent.renderer.material.shader = shader1;
  }

  for (var child : Transform in transform) {
    SetShaderRecursive (child);
}