Hi,
I want to set a MID to my render mesh niagara at runtime. So I use MeshRendering.OverrideMaterials.UserParamBinding
I can use SetVariableMaterial("BrokenWallMat", MID)
to control the niagara emitter mesh.
But I also need Bindings.MaterialParameterBindings to change material.
Fin, I found that SetVariableMaterial doesn’t work.
In SourceCode I find:
SetVariableMaterial
will call UpdateEmitterMaterials(true)
in UE4.27 or UpdateEmitterMaterials()
in UE5.
UE4:UpdateEmitterMaterials(bool bForceUpdateEmitterMaterials)
//....
Emitter->ForEachEnabledRenderer(
[&](UNiagaraRendererProperties* Properties)
{
// Nothing to do if we don't create MIDs for this material
if ( !Properties->NeedsMIDsForMaterials() )
{
return;
}
TArray<UMaterialInterface*> UsedMaterials;
Properties->GetUsedMaterials(EmitterInst, UsedMaterials);
uint32 MaterialIndex = 0;
for (UMaterialInterface*& ExistingMaterial : UsedMaterials)
{
if (ExistingMaterial)
{
bool bCreateMID = true;
if ( ExistingMaterial->IsA<UMaterialInstanceDynamic>() )
{
if ( EmitterMaterials.FindByPredicate([&](const FNiagaraMaterialOverride& ExistingOverride) -> bool { return (ExistingOverride.Material == ExistingMaterial) && (ExistingOverride.EmitterRendererProperty == Properties) && (ExistingOverride.MaterialSubIndex == MaterialIndex); }) )
{
if ( bForceUpdateEmitterMaterials )
{
// Forcing an update means create a new MID so grab the parent from the existing one
ExistingMaterial = CastChecked<UMaterialInstanceDynamic>(ExistingMaterial)->Parent;
}
else
{
// We found one so no need to create but make sure we keep it for tracking
FNiagaraMaterialOverride& NewOverride = NewEmitterMaterials.AddDefaulted_GetRef();
NewOverride.Material = ExistingMaterial;
NewOverride.EmitterRendererProperty = Properties;
NewOverride.MaterialSubIndex = MaterialIndex;
bCreateMID = false;
}
}
}
// Create a new MID
if ( bCreateMID )
{
//UE_LOG(LogNiagara, Log, TEXT("Create Dynamic Material for component %s"), *GetPathName());
ExistingMaterial = UMaterialInstanceDynamic::Create(ExistingMaterial, this);
FNiagaraMaterialOverride Override;
Override.Material = ExistingMaterial;
Override.EmitterRendererProperty = Properties;
Override.MaterialSubIndex = MaterialIndex;
NewEmitterMaterials.Add(Override);
}
}
++MaterialIndex;
}
}
);
//...
UE5 is same excepet UMaterialInstanceDynamic::Create
part
because all my emitter is mesh render emitter. so !Properties->NeedsMIDsForMaterials()
is:
virtual bool NeedsMIDsForMaterials() const override { return MaterialParameterBindings.Num() > 0; }
so each enable renderer will create MIDs which MaterialParameterBindings was set.
but UsedMaterials are the MIDs which I use SetVariableMaterial
set.
fin, It will run to UMaterialInstanceDynamic::Create, but the ExistingMaterial is a MID I set. But ParentMaterial is a MID, so the MID which were create Parent is null and have som Warning
At last, the niagara won’t render my SetVariableMaterial
MID.
It is same in UE5.0.2
both of them, do nothing if ExistingMaterial is a MID and not found in EmitterMaterial.
I check the Properties
, the MaterialParameterBindings is in it.
if I set ExistingMaterial to Override.Material not create, it also have the MaterialParameterBindings Parameter.
Are there we need to recreate a MID when we SetVariableMaterial ?
Or How can I set MID to niagara when niagara have MaterialParameterBindings ,and my MID will work ?