Material Instances and Dynamic Material Instances¶
A material describes how a surface is shaded. A material instance edits exposed parameters without recompiling the parent material. A dynamic material instance is the runtime copy you can change while the game is playing.
The one-minute version¶
- A Material is the parent shader graph. It defines which parameters exist.
- A Material Instance is an asset that inherits from a parent material and overrides exposed parameters in the editor.
- A Dynamic Material Instance (DMI or MID) is a runtime object you can change from Blueprint during play.
- You can only change values that the parent material exposed as parameters: scalar, vector/color, texture, and similar parameter nodes.
- Changing a material asset or shared material instance can affect every mesh using it. Changing a DMI affects the mesh/component using that DMI.
- Store the DMI you created. Later
Set Scalar Parameter Valuecalls must target that same dynamic instance.
The family tree¶
M_Enemy_Master
defines parameters:
TintColor
DamageFlashAmount
EmissiveStrength
MI_Enemy_Red
parent = M_Enemy_Master
TintColor = red
Runtime DMI on EnemyMesh
parent = MI_Enemy_Red or M_Enemy_Master
DamageFlashAmount changes during gameplay
The parent material owns the graph and parameter names. Instances own overrides. Dynamic instances own runtime overrides.
If the parent material has no parameter named DamageFlashAmount, a Blueprint
call with that name has nothing useful to change.
Material Instance assets¶
Use regular Material Instance assets for authored variants:
- red, blue, and gold enemy skins;
- rough vs polished versions of the same floor material;
- weapon rarity colors;
- UI material variants;
- cheap tuning without recompiling the parent material.
They are content assets. You edit them in the editor, assign them to meshes, and reuse them across many objects.
Do not create a new parent material every time you want a color variant. Expose
a Vector Parameter such as BaseColorTint, create instances, and override that
parameter.
Dynamic Material Instances¶
Use a DMI when a value must change during play:
- flash red when damaged;
- dissolve over one second;
- fill a progress material;
- pulse emissive intensity;
- change team color on one spawned actor;
- fade a hologram locally.
Typical Blueprint setup:
BeginPlay
-> Mesh Create Dynamic Material Instance
Element Index = 0
-> Store Return Value as BodyDMI
OnDamageTaken
-> BodyDMI Set Scalar Parameter Value
Parameter Name = DamageFlashAmount
Value = 1.0
-> Timeline fades value back to 0.0
The stored variable is the important part. If you create a DMI, ignore the return value, and later call parameter setters on the original material, you are not changing the runtime copy used by the mesh.
Which Create Dynamic Material Instance node?¶
Blueprint exposes more than one useful path:
| Node shape | What it is for |
|---|---|
| Create Dynamic Material Instance from Kismet Material Library | Create a DMI from a parent material. You still need to assign it to a mesh/material slot if you want it rendered there. |
| Create Dynamic Material Instance on a Primitive Component | Create a DMI for a component material element and assign it to that element. This is the common mesh workflow. |
Beginners usually want the component version:
StaticMeshComponent
-> Create Dynamic Material Instance(Element Index 0)
-> store returned DMI
That connects the runtime material to the mesh slot in one step.
When it fails¶
| Symptom | Likely cause | Fix shape |
|---|---|---|
| Parameter change does nothing | Parameter name does not exist, spelling/case differs, or the material input is not parameterized. | Open the parent material and confirm the parameter node name. |
| Every enemy changes color | You changed a shared material/instance asset instead of a DMI per enemy. | Create/store a DMI for each mesh that needs unique runtime state. |
| Only one material slot changes | You created a DMI for element index 0, but the visible surface uses another slot. | Check mesh material element indices. |
| Later calls do nothing | The DMI variable is None or you did not store the returned DMI. |
Store and guard the return value. |
| Multiplayer clients disagree | You changed only local presentation. | Replicate the gameplay state, then let each client update its local DMI. |
Parameter setters usually fail quietly. A wrong parameter name is not an exception. Use a visible test value and print the DMI reference while debugging.
What they do not do¶
- A DMI does not add a parameter to a material that lacks one.
- A DMI does not automatically apply itself to every mesh.
- A material parameter change does not change collision, damage, AI, or tags.
- A material instance is not a widget style or gameplay data table.
- A local DMI change does not replicate by itself.
- Creating DMIs every Tick is wasteful; create once, store, then update values.
The pattern everyone actually uses¶
For a damage flash:
BeginPlay
-> Mesh Create Dynamic Material Instance Element 0
-> Set BodyDMI
OnHealthChanged
-> BodyDMI Set Vector Parameter Value HitTint = red
-> BodyDMI Set Scalar Parameter Value FlashAmount = 1
-> Timeline 0.15 seconds
Update:
BodyDMI Set Scalar Parameter Value FlashAmount = Alpha fading to 0
For team color:
OnRep_TeamId or BeginPlay after team assigned
-> TeamColor = Map TeamId to LinearColor
-> BodyDMI Set Vector Parameter Value TeamColor
The replicated value is the team ID. The material update is local visual presentation derived from that state.
Lookalikes - which one do I want?¶
| Tool | Use when | Watch out |
|---|---|---|
| Material | You need to define the shader graph and available parameters. | Editing it can trigger recompilation and affect all children. |
| Material Instance | You need authored variants in the editor. | It is shared when assigned to many meshes. |
| Dynamic Material Instance | One runtime mesh/component needs unique changing parameters. | Store it and assign/use the correct material slot. |
| Set Material | You want to replace a component's material slot. | Replacing is different from changing a parameter. |
| Material Parameter Collection | Many materials need one global value. | It is global, not per actor. |
| Niagara parameter | A particle effect needs runtime values. | Niagara component parameters are separate from mesh materials. |
Rule of thumb: parent material defines knobs, material instance sets authored knobs, dynamic material instance changes knobs at runtime.
Going deeper¶
- Actor, Scene, and Primitive Components - why mesh material slots live on primitive components.
- Set Actor Hidden In Game / Set Visibility - visual changes vs gameplay disable.
- Lerp, FInterp To, and moving things smoothly - driving material values smoothly over time.
- Replication basics - replicate the gameplay state, not the local material function call.
- Official docs: Instanced Materials, Creating and Using Material Instances, and Create Dynamic Material Instance.
- Engine source (requires engine access - we do not reproduce it here):
UMaterialInstanceDynamic::CreateinEngine/Source/Runtime/Engine/Private/Materials/MaterialInstanceDynamic.cpp; Blueprint helperUKismetMaterialLibrary::CreateDynamicMaterialInstanceinEngine/Source/Runtime/Engine/Private/KismetMaterialLibrary.cpp; component material-slot helpers such asUPrimitiveComponent::CreateDynamicMaterialInstanceinEngine/Source/Runtime/Engine/Private/Components/PrimitiveComponent.cpp.