Player skins require too many material instances

Hello!

I have modular vehicles, which consists of 7 modules, each can be painted with 15 different paints.
I have 2 master materials - one for module on vehicle and one for dropped module.
This results in 2 * 15 = 30 material instances per module or roughly 600 material instances for all vehicle modules in the game. Feels a lot of manual work.

I am considering creating dynamic material and feeding it with properly named textures found by FindFiles (didn’t try it yet). Am I going in the right direction? How do I reduce amount of manual drags and drops without hurting performance?

This is my material.

I think Dynamic Materials + Blueprints is an option worth exploring.

Excellent videos by Zac on this topic:

https://www.youtube.com/watch?v=i2XmTbfIJ3s

I solved this using Dynamic Material and Data Tables.

SkinComponent holds pointers to UpdatedComponent (MeshComponent) and SkinDataTable.
On BeginPlay it creates and assigns dynamic material to UpdatedComponent.
When SetSkinName is called SkinComponent fetches textures from data table and sets material parameters.

This way I need only 2 (not 30) material instances per module and I can quickly populate data table with script (no manual drag and drop).

void USkinComponent::BeginPlay()
{
	Super::BeginPlay();
	
	check(SkinDataTable);

	if (!UpdatedComponent) return;
	Material = UpdatedComponent->CreateAndSetMaterialInstanceDynamic(0);
	
	SetSkinName(SkinName);
}

void USkinComponent::SetSkinName(const FName& Name)
{
	if (SkinName == NAME_None) return;
	
	FSkinData* SkinData = SkinDataTable->FindRow<FSkinData>(Name, ContextString);
	if (!SkinData) return;

	SkinName = Name;
	
	if (!Material) return;
	Material->SetTextureParameterValue(BaseColor, SkinData->BaseColor.LoadSynchronous());
	Material->SetTextureParameterValue(Normal, SkinData->Normal.LoadSynchronous());
	Material->SetTextureParameterValue(OcclusionRoughnessMetallic, SkinData->OcclusionRoughnessMetallic.LoadSynchronous());
}

This is csv for data table:

Name,BaseColor,Normal,OcclusionRoughnessMetallic
0,"Texture2D'/Game/Meshes/HullLight/Textures/T_HullLight_00_D.T_HullLight_00_D'","Texture2D'/Game/Meshes/HullLight/Textures/T_HullLight_00_N.T_HullLight_00_N'","Texture2D'/Game/Meshes/HullLight/Textures/T_HullLight_00_M.T_HullLight_00_M'"
1,"Texture2D'/Game/Meshes/HullLight/Textures/T_HullLight_01_D.T_HullLight_01_D'","Texture2D'/Game/Meshes/HullLight/Textures/T_HullLight_00_N.T_HullLight_00_N'","Texture2D'/Game/Meshes/HullLight/Textures/T_HullLight_00_M.T_HullLight_00_M'"