- Create a master material
- Create a scalar parameter in it
- Create a material instance off of it
- Assign it to a static mesh, include it in an actor
- In the actor’s BeginPlay, call SetScalarParameterOnMaterials
Expected result: the material will update itself, reflecting the changes in the scalar parameter.
Actual result: roughly one in ten times the material doesn’t update its scalar parameter’s value.
The behavior seems to happen at random, about 90% of the time it works fine. As a workaround, I’ve tried inserting a Delay node of 0.5 seconds before calling SetScalarParameterOnMaterials.
UPDATE: it seems that BeginPlay has nothing to do with it. SetScalarParameterOnMaterials is always erratic. It works most of the time, except in about 10% of invocations. I can’t edit the description so I’m adding this as a comment.
Why don’t you use dynamic material instance instead?
I’ve tried using those too, same problem. It seems that it’s not the parameter that’s not being set - it’s the subsequently queued up render command that won’t get executed.
I believe the problem lies in Engine\Source\Runtime\Engine\Private\Materials\MaterialInstance.cpp
There’s a method called GameThread_UpdateMIParameter there with a macro: ENQUEUE_UNIQUE_RENDER_COMMAND_FIVEPARAMETER_CREATE_TEMPLATE
Now I don’t know much about UE4’s rendering pipeline, but I did some quick debugging against the source code of 4.15.2 and it seems that this render queueing logic is the culprit.
If any dev could look at it that would be great. In 4.15.2, the method on line 317 in MaterialInstance.cpp.
For reference, I’ve attached both my actor’s construction script and relevant parts from its event graph.
Resolved by changing my mesh spawning logic