Dynamic material instance being set to NULL

Bit of a newbie to UE4 so I may be missing something obvious. I am trying to change the colour of a static mesh using C++. I read that Dynamic material instances were the way to go here. My understanding is that you can create an instance in BeginPlay, and then set the parameters of that material during the game.

Here is what I went for:

Header:

	UPROPERTY()
	UMaterialInstanceDynamic* Material;

CPP:

// ctor
	static ConstructorHelpers::FObjectFinder<UMaterial> NodeMaterial(TEXT("Material'/Game/Teleportation/TeleportNodeMaterial.TeleportNodeMaterial'"));

	if (NodeMaterial.Succeeded()) {
		Mesh->SetMaterial(0, NodeMaterial.Object);
	}

void ATeleportNode::BeginPlay()
{
	Super::BeginPlay();
	// This works as I thought
	Material = UMaterialInstanceDynamic::Create(Mesh->GetMaterial(0), NULL);
	Material->SetVectorParameterValue(TEXT("BaseColor"), FLinearColor::Red);
	Mesh->SetMaterial(0, Material);
}

// Using the Material later
void ATeleportNode::OnTeleportFrom_Implementation()
{
	Occupied = false;

for (ATeleportNode* node : ConnectedNodes) {
	// Material is now NULL
	if(node->Material)
		Material->SetVectorParameterValue(TEXT("BaseColor"), FLinearColor::Red);
		Mesh->SetMaterial(0, Material);
}
}

I thought it was possible to have a member variable store the dynamic material, but later when I try to use it, the pointer is NULL. It seems like the instance is being destroyed somewhere once BeginPlay has been run, but I can’t see where.

This is the way I set up my Material Instances, this will also directly set your new material, I adjusted it to your variable names:

Material = Mesh->CreateAndSetMaterialInstanceDynamicFromMaterial(0, Mesh->GetMaterial(0));

Maybe this will work?! :slight_smile:

If that doesn’t work either check if your Mesh is not a nullptr

Hey, thanks for that didn’t spot that function. Unfortunately hasn’t fixed my problem. Mesh isn’t a nullptr either.

There was an ordering issue with the above, the BeginPlay here was running too late. I’ve moved all the code from BeginPlay to the ctor instead, but still seeing the Material not being saved as a member.

I ran into the same problem. While the pointer variable is set to null, you can retrieve the material instance dynamic from the mesh after creating and setting it like this…

solved my issue.

auto Mat = Cast<UMaterialInstanceDynamic>(Mesh->GetMaterial(0));
if (Mat)
{
	Mat->SetScalarParameterValue("Selected", 1);
}