Blueprint: Any way to set all materials?

Right now, we have objects with 4 or 5 materials. When we want to apply a “ghost” material to these objects, we currently need to override all the materials on the object with the “ghost” material.

What we’d really like is a way that we could use the “Set Material” action in the Blueprint graph to set them all.

This is especially true since our actor has about a dozen different components inside it, and setting 4 materials on each of 12 components gets out of hand fast.

Unfortunately, there doesn’t seem to be a way to set the “Element Index” to something other than a single constant value, and it doesn’t accept multiple “Make Literal Int” functions as inputs.

I’ve also tried making a custom “Set All Materials” function in Blueprint that will accept a PrimitiveComponent input and a MaterialInterface input, so I can replace all the “Set Material” actions with my custom function. It looks like this:

Unfortunately, I am seeing that the PrimitiveComponent input pin will only accept ONE input, meaning I can’t connect all 12 of my components to this function the way I can with “Set Material.”

There also seems to be a default “Target” input pin on this function when I place it, but trying to connect any of my components to it gives me the floating popup message "Object ‘StaticMeshComponent’ is not compatible with object ‘self’ "

Any ideas?

I made this Blueprint setup for you. Hope it helps. :slight_smile:

1 Like

Thanks, Satheesh – That’s very helpful!

I was able to get something like this working. However, I found it was problematic to put this in a Blueprint function since I needed this to be shared across many object types, and for various reasons I needed to put the function in a grandparent class which was non-blueprintable.

So I ended up doing it in code like so:

Header file:

UFUNCTION( BlueprintCallable, Category=OurGame)
void SetMaterialForAllComponents( UMaterialInterface * NewMaterial );

CPP file:

void AOCBuildingTile::SetMaterialForAllComponents( UMaterialInterface * NewMaterial )
{
	for( auto it = Components.CreateConstIterator(); it; ++it )
	{
		UStaticMeshComponent * pMeshComponent = Cast(*it);

		if ( pMeshComponent )
		{
			for ( int i = 0; i < pMeshComponent->GetNumMaterials(); ++i )
			{
				pMeshComponent->SetMaterial( i, NewMaterial );
			}
		}
	}
}

Another way to do it might be to use Material Parameter Collection and use those Params in all your materials.

This is excellent! I tweaked the setup slightly to first store all materials in an array and then swap them out all in the construction script, and then later I can access that array to reapply the original materials in the event graph. Thank you!