Create Material Instance in plugin

Hello,
I’m trying to write a plugin to create material instance, the plugin will apply it to a specific actor in the current level, but I don’t know how to create that.

Can I put material instances directly into the plugin? Or do i have to generate it using c++?

I found some keywords like “HLSL”, should I learn it first?

Any reply will help me, thanks.

1 Like

Material instances are always derived from a base material. In the base material, you define some values as parameters, which can be changed in the instance programatically. So, an instance without a base material does not exist. Means, that you would need to include that material in the plugin as well.

Material instances can be created as assets in content browser: use Right mouse button context menu > Create Material Instance.

Or they can be created as dynamic material instance, either in Blueprint or C++. In this case, you can set material parameter values in your program code dynamically.

The question is: what do you want to achieve? A plugin just to create or assign a material instance to an actor sounds like being far to complicated. Create your base material, define your parameters, then create your instance(s) either statically or dynamically and assign to the actor. But you can create so called Content Only plugins, so here you could include your materials.

HLSL is the shading language behind the materials. In 99% of all cases, you will not need to deal with this, instead just use Unreal materials with all the functionality they offer. HLSL can be useful if you want to create custom material nodes. But this should only be done if absolutely needed, because for example it does not get optimized. One example can be the need of for loops, which are possible in HLSL but not in UE4 materials.

You definitely should check the fantastic tutorials by Mathew Wadstein, like WTF Is? A Material Instance in Unreal Engine 4 - YouTube and many others. His channel is absolutely fantastic.

I hope I did understand correctly, what you want to achieve.

1 Like

Thanks for your reply.

I know how to create material instance by Editor UI(Content Browser), but I need to achieve using C++ code.

What I want to achieve is to quickly generate a SceneCapture of a specific actor, and my plugin is Editor Toolbar Button, does this mean the plugin cannot include materials?

Here’s some quick C++ example for creating a dynamic material instance.

UMaterial* TestMaterial;

TestMaterial = LoadObject<UMaterial>(nullptr, TEXT("Material'/Game/Path/M_TestMaterial.M_TestMaterial'"));

// for the material instance
UMaterialInstanceDynamic* MI_TestMaterial = nullptr;

// just some example with a scalar parameter value
if (TestMaterial)
{
	MI_TestMaterial = UMaterialInstanceDynamic::Create(TestMaterial, this);
	MI_TestMaterial->SetScalarParameterValue(TEXT("Radius"), 0.0f);
}

// apply the material instance to some static mesh
StaticMesh->SetMaterial(MI_TestMaterial, 0);

There’s also a UMaterialInstanceConstant | Unreal Engine Documentation available, but i never used that… should go somewhat like

UMaterialInstanceConstant* instance = NewObject<UMaterialInstanceConstant>(...)

There should be no problem to include the materials in your plugin, a plugin can contain code and assets.

2 Likes

Thanks, it really help me.

One big problem is that the Material Instance Dynamic I created using your method is completely different from my original Material Instance. I already follow the material path from this(C++ : Access to Plugin Assets), any ideas?

Create from C++ code

Thanks @herb64 for giving me some clues,and I finally solved this problem.

Here is my code

	U_Material* M_YourMaterial = LoadObject<UMaterial>(nullptr, TEXT("Material'/YourPath/M_YourMaterial.M_YourMaterial'"));

	// Load necessary modules
	FAssetToolsModule& AssetToolsModule = 
		FModuleManager::Get().LoadModuleChecked<FAssetToolsModule>("AssetTools");

	if (M_YourMaterial)
	{
		UMaterialInstanceConstantFactoryNew* Factory =
			NewObject<UMaterialInstanceConstantFactoryNew>();
		Factory->InitialParent = M_YourMaterial ;

		FString PackageName = "/Game/YourPath/";
		FString MaterialBaseName = "MI_YourMaterial_";
		FString Name = MaterialBaseName += FString::FromInt(YourActor->GetUniqueID());

		MI_YourMaterial = CastChecked<UMaterialInstanceConstant>(
			AssetToolsModule.Get().CreateAsset(Name, 
				FPackageName::GetLongPackagePath(PackageName),
				UMaterialInstanceConstant::StaticClass(), 
				Factory)

		// You can set the MI_YourMaterial information here

		);

By the way, UMaterialInstanceConstant requires “UnrealEd” dependency, and the difference between UMaterialInstanceConstant and UMaterialInstanceDynamic is that the former is changed in Editor and the latter is changed after BeginPlay.

As a side note,

Can plugin include uasset?
Yes, make sure you have “CanContainContent” : true in your MyPlugin.uplugin, then you can add .uasset.
How to show plugin folder in Content Browser?
Check Content Browser ->Settings->Show Plugin Content to see the plugin folder in Content Browser.
image

1 Like

So, you can with C++, I have this done.
Activate material instance components, it’s just like a component, it an interface.

You must have UMaterialInterface * pointer. Load the material with the component. Then once you got the interface you got to create an istance and make a load command. After this there is like many ways to do this, you can write your own textures and so on. At the end you set the texture parameters and set material. You need parameters on the material :slight_smile: