Build failed with error: 'SetMaterial': is not a member of 'UStaticMesh'

I am working on a project where I am assigning materials on a UStaticMesh during runtime using UStaticMesh::SetMaterial. I have a references in my code to StaticMeshes in my content browser, and instances of these objects I have placed out with foliage is updated during runtime. It’s working correctly on PIE, but when I try to build, i get an error:

“SetMaterial’: is not a member of 'UStaticMesh”, while it clearly is:

I would appreciate any help I could get with this

Hey, SetMaterial on staticMesh is surrounded with “#if WITH_EDITOR” so that mean it wont be availliable in packaged game. That allow more optimisation i guess.
but the call in PIE shouldn’t work and should log an error

could you share a bit of your code ? ( what type of foliage are you using ? etc, might help to find a workarround )

The foliage consists of 2 tree meshes with two material elements each. This is the code:

Game mode.h:

	UPROPERTY(EditAnywhere, Category = Foliage)
	TArray<UStaticMesh*> Meshes;

	UPROPERTY(EditAnywhere, Category = Foliage)
	TArray<int> NumberOfMaterials;

	UPROPERTY(EditAnywhere, Category = Foliage)
	TArray<UMaterialInterface*> PhysicalMaterials;

	UPROPERTY(EditAnywhere, Category = Foliage)
	TArray<UMaterialInterface*> SpiritMaterials;

	void ToggleInstanceMeshes();

.cpp (//I know it a very crude, convoluted way of making it happen, but it works in PIE. Its just basically switching between two sets of materials on the correct material element on the correct mesh):

void ToggleInstanceMeshes()
{
int MeshIndexAccumulator = 0;

		for (int i = 0; i < Meshes.Num(); ++i)
		{
			if (NumberOfMaterials[i])
			MeshIndexAccumulator += NumberOfMaterials[i];

			int MaterialElementIterator = 0;
			for (int j = MeshIndexAccumulator - NumberOfMaterials[i]; j < MeshIndexAccumulator; ++j)
			{
				if (Meshes[i])
				{
					if (bIsSpiritWorld) Meshes[i]->SetMaterial(MaterialElementIterator, SpiritMaterials[j]);
					else Meshes[i]->SetMaterial(MaterialElementIterator, PhysicalMaterials[j]);
				}

				MaterialElementIterator++;

			}
		}
}

I suggest you do your materials this way :

    PhysicalWorldMat   --
                         |
                         |-> Lerp between them, with a Material collection parameter    
                         |->     ( name exemple :   IsSpiritualVision )
                         |
    SpiritualWorldMath --

and in c++ you can use it like that:

SpiritualVisionParameters = LoadObject<UMaterialParameterCollection>(NULL, TEXT("MaterialParameterCollection'/Game/PostProcess/SpiritualVisionParams.SpiritualVisionParams'"), NULL, LOAD_None, NULL);


UKismetMaterialLibrary::SetScalarParameterValue(world, SpiritualVisionParameters , "IsSpiritualVision", newModeIsSpiritualVision ? 1 : 0);

this way you could also be able to make a smooth blend if you need

doc : Material Parameter Collections | Unreal Engine Documentation

Hey thank you so much for showing me this. Until now I only knew about changing material parameters during runtime with dynamic material instances. I ended up just putting all the textures into one material, and used material parameter collections to toggle visibility of all of them. Thanks!