Make copy of Master material

I’m writing a plugin and wish to make a copy of a MasterMaterial, switch out the textures and apply to a UStaticMesh.

This is how I get my MasterMaterial.

FString matPath = "Material'/Game/MasterMaterial.MasterMaterial'";
UMaterialInterface * material = Cast<UMaterialInterface >(StaticLoadObject(UMaterialInterface::StaticClass(), nullptr, *(matPath)));
if (material)
{
     UStaticMesh *myMesh = Cast<UStaticMesh>(ImportedAssets[0]);
     //make a copy
     //change the textures
     //apply to UStaticMesh
}

Why would you want to make a copy of the material? to change the texture parameter value you can create a dynamic material instance and set it as one of the material for a StaticMeshComponent (or PrimitiveComponent). There are a lot of ways to do this, but the most common one is by using UPrimitiveComponent::CreateDynamicMaterialInstance.

But if you are really trying to copy a master material and assign it to a static mesh (instead of static mesh component), then you are trying to duplicated a material asset and change one or more material node in it (this is anything but trivial, lots of kismet mumbo jumbo in there), and then assign it as a specific material in a static mesh asset and mark the static mesh package as dirty. It can be done (although you need to tweak the engine code a bit) but are you sure you want to do it?

You see, StaticMesh, Material and MaterialInstance are usually assets, which means they are not intended to be changed at runtime. Runtime editable version of a static mesh would be UStaticMeshComponent, and Runtime editable version of Material is DynamicMaterialInstance.

if I make a Dynamic material instance like :

UMaterialInstanceDynamic *test = UMaterialInstanceDynamic::Create(material, NULL);

how do I apply it to my UStaticMesh. As far as I can see UStaticMesh does not have a SetMaterial function.
I would like to make changes to ‘test’ so that the MasterMaterial is not affected.

you can directly change the material in a static mesh by accessing the public materials array:

	/** Materials used by this static mesh. Individual sections index in to this array. */
	UPROPERTY()
	TArray<UMaterialInterface*> Materials;

This array, eventhough it is public, is not meant to be changed manually (unless you know what you’re doing and you’re doing it in editor context instead of standalone). The safest way to change materials at runtime would be from UPrimitiveComponent (UStaticMeshComponent is a primitive component), there are lots of material related functions there:

I have a UStaticMesh myMesh. I can do
UMaterial *mat = myMesh->GetMaterial(0)->GetMaterial()

But if I do mat = test and make changes to mat. The original MasterMaterial is changed which I want to remain intact.

That’s what I said in my first post, what you are trying to do is to duplicate a material and change the texture… but do you really really want to do it? because I don’t think you are. Let me ask you a question, sorry if it offends you, do you know about MaterialInstance and its uses? if you don’t know then you should definitely need to learn about it, but if you do know about it, then I have given you a hint on how you can achieve it: create a package, duplicate the material, put it in the package, change the texture of that material, and finally change the static mesh texture and mark all of the packages that you’ve changed to dirty.

Yes I want to duplicate a material. My plugin will be importing multiple assets and i want to apply a MasterMaterial that I have created to all these assets.
Maybe I’ve not been able to make it clear what I’m asking.
Anyways thanks for the help. I shall read up on what you mentioned.