Why is "Cast To MaterialstanceDynamic" not working in some cases in the ConstructionScript?

So I’ve made a simple function (in a BlueprintFunctionLibrary) to change the color of an object based on its team.

(The “Colors” array is hard-coded local variable in the function)

I use it in 2 of my classes’ ConstructionScripsts: a Character and an Actor

Now the end result looks the same in both cases - the mesh does change its color.

However, while the Character is going through “CREATE material” once and then only changes it, the Actor is constantly creating new materials (cast fails all the time)!

The thing that puzzles me the most is that when I put the function in the TickEvent() graph of the Actor it starts working as intended (1 create and many changes).

Can someone explain this behavior?

If your Actor holds the variables referencing the MDI, then there is nothing there until the Constructor is finished. It just doesnt exist yet.

So Beginplay is probably a better node for using the MDIs and setting their params, but i think it works okay to create the MDIs and set the variables that reference them.

Well the Actor holds its Mesh component. The Character also holds its SkeletalMesh Component. Both should already exist when placed in the level.

Non of them holds an explicit variable to the MDI. I thought I don’t need it as I can take the material from the mesh anyway.

Character Construction Script:

Actor Construction Script:

I need the function in the construction script to be able to see the Teams while I’m building the level. This is also a debug function which makes it kind of ok to spam with materials.

…but I don’t understand why it happens and this drives me nuts.

I thought that this might be caused by the materials but it’s not. I’ve swapped them and still the same result.

I could be wrong but as far as I have observed in my own development efforts, the actor is NOT placed in the level until AFTER the construct function is done, and the BeginPlay function fires.
The Actor might exist somewhere in memory, but I think it is not actually placed in the level until then.
But maybe the components are initialized enough to make an MDI off of them before then. I’m not sure. Your problem could be something else but this seemed like a good place to start looking.

Why not try moving it to BeginPlay and see if it works (even if it gets the team color wrong?)

Why the Actor might not exist while the Character is proven to exists?

The thing I’m trying to understand here is: “Why the Cast node WORKS for the Character but does not work for the Actor in the same setup.”

What is the difference in initialization process for Characters and Actors?

As explained above the script works correctly in Tick which means it will work fine in BeginPlay.

Why are you trying to cast a Material to a MaterialInstanceDynamic? I don’t know much about those things but that seems like a strange thing to do and I’m not sure how it could work. I don’t think MaterialInstanceDynamic is a child class of Material or anything like that, so if I’m right, it would never work to cast from the one to the other no matter what.

I thought it was clear why I cast it. To create it if it is not already dynamic.

MaterialInstanceDynamic is derived from MaterialInstance. (documentation)

I think that cast doesnt change one thing into another, it just treats it as that other thing. So I dont think casting will magically make a material create a dynamicmaterialinstance and then assign that mdi to the reference that used to be a material.

I think you need to just create a dynamic material instance the normal way, not by trying to cast to it from a parent class.

Nope. It does not change it. This is why I use the “CreteDynamicMaterialInstance” node.

I’ll remind you that it works as intended on a Character but not an an Actor. I don’t know why…

that’s good. CreateDynamicMaterialInstance is the right way to do it. But that’s not working on an Actor? It requires a component to be plugged in that has a mesh with at leadt one Material slot. Are you plugging in one of those on the actor?

Yep. You can see the construction script setup in my second answer.

They both work. (change colors) However, the Actor creates new material instances like crazy while the Character just makes one and changes it (as intended).

That’s pretty weird. I don’t know why that’s happening and wish I could help better.
I had an equally weird idea though: What if you created the MDI outside of the class that uses it, like some kind of singleton actor or the GameInstance? Not the best practice probably but maybe it would stop it from being so loopy.