UMaterialInstance vs UMaterialInstanceDynamic

I’ve been searching for an answer for changing the TextureParameterValue of a material instance from code but had no luck. So here’s the problem. In my Playercontroller I made this simple code:

TestDesktopPlayerController.h:

UCLASS()
class ATestDesktopPlayerController : public APlayerController
{
	GENERATED_BODY()

public:
	UPROPERTY(BlueprintReadWrite, EditAnywhere)
	UTexture2D* mCustomTexture;

	UPROPERTY(BlueprintReadWrite, EditAnywhere)
	UMaterialInstanceDynamic* mCustomMaterial;

	ATestDesktopPlayerController();
};

TestDesktopPlayerController.cpp:

ATestDesktopPlayerController::ATestDesktopPlayerController()
{
	bShowMouseCursor = true;
	bEnableClickEvents = true;
	bEnableTouchEvents = true;
	DefaultMouseCursor = EMouseCursor::Crosshairs;

	int32 width = 40;
	int32 height = 40;
	TArray<FColor> data;
	for (int32 i = 0; i < 1600; i++)
	{
		data.Add(FColor(0, 0, 255, 255));
	}
	FCreateTexture2DParameters params;
	params.bDeferCompression = false;
	params.bSRGB = true;
	params.bUseAlpha = true;
	params.CompressionSettings = TextureCompressionSettings::TC_Default;
	params.SourceGuidHash = FGuid::NewGuid();
	mCustomTexture = FImageUtils::CreateTexture2D(width, height, data, this, FString(TEXT("CustomTexture")), EObjectFlags::RF_Public, params);

	// Structure to hold one-time initialization
	struct FConstructorStatics
	{
		ConstructorHelpers::FObjectFinderOptional<UMaterialInstanceDynamic> ChildMaterial;
		FConstructorStatics() : ChildMaterial(TEXT("Material'/Game/Material/ChildMaterial.ChildMaterial'")){}
	};
	static FConstructorStatics ConstructorStatics;
	if (ConstructorStatics.ChildMaterial.Succeeded())
	{
		mCustomMaterial = ConstructorStatics.ChildMaterial.Get();
	}

	if (mCustomMaterial && mCustomTexture)
	{
		mCustomMaterial->SetTextureParameterValue(FName("Diffuse"), mCustomTexture);
	}
}

I made ChildMaterial as material instance from ParentMaterial in UE editor.

94075-path.jpg

Everything seems to be in place and I’ve seen many samples in Answerhub and Forum that use UMaterialInstanceDynamic, instead of UMaterialInstance, to manipulate textures. The problem is, UE cannot find my ChildMaterial material instance if I use ConstructorHelpers::FObjectFinderOptional with UMaterialInstanceDynamic as template parameter.

94076-not+found.jpg

But if I change it to ConstructorHelpers::FObjectFinderOptional with UMaterialInstance as template parameter, then it can be found. Is this a bug in UE?

What’s the difference between UMaterialInstance and UMaterialInstanceDynamic? When is the perfect time to use each of them?

Because I notice that UMaterialInstanceDynamic is a subclass of UMaterialInstance. So why can’t ConstructorHelpers::FObjectFinderOptional find the asset?

Hello,

After looking into your issue, the problem here seems to be that you’re looking to a UMaterialInstanceDynamic, but your ChildMaterial is a UMaterialInstance.

ConstructorHelpers::FObjectFinderOptional<UMaterialInstanceDynamic> ChildMaterial;

Based on your screenshot of the Material Instance, it appears that Child Material is a UMaterialInstance, which would be why you are unable to find it when searching for a Dynamic Material Instance.

Think of it like this:

You have an Actor class in your game. You use FObjectFinder to try and find a Pawn class. Your original class is an Actor, and even though Pawn is a subclass, it will not be able to find the parent class.

Based on what I’m seeing here, it would appear that in order to find the MaterialInstanceDynamic, you’d need to first create one and then search for it.

Also, just for reference, here’s our documentation on Material Instances: Instanced Materials | Unreal Engine Documentation

Let me know if that doesn’t make sense or you think it’s not correct, and I’ll be glad to try and provide additional information.

Have a great day