Is it possible to create a UMaterialInstanceDynamic inside an actor constructor?
if not, is there any other place that I can do it besides “BeginPlay”?
Many thanks.
Cheers,
J
Is it possible to create a UMaterialInstanceDynamic inside an actor constructor?
if not, is there any other place that I can do it besides “BeginPlay”?
Many thanks.
Cheers,
J
Hi J,
Technically you can with:
if (ParentMaterial)
{
BaseMaterialMID = UMaterialInstanceDynamic::Create(ParentMaterial, nullptr, FName(TEXT("Base Material Dynamic")));
BaseMaterialMID ->SetFlags(RF_Transient);
}
However, if the ParentMaterial is set as a property in a BP child of this class then the above won’t work as the C++ construction happens first prior to any of the BP vars being set.
In this case, you need to make a function of the above code like so:
void AYourActorClass::SetActorMaterial(UMaterialInterface* ParentMaterial, bool bInConstructor)
{
if (ParentMaterial)
{
BaseMaterialMID = UMaterialInstanceDynamic::Create(ParentMaterial, this, FName(TEXT("Base Material Dynamic")));
if (bInConstructor)
{
// Set new object flag to RF_Transient since this is being called in the BP child constructor
BaseMaterialMID->SetFlags(RF_Transient);
}
}
}
THEN call this function in your BP Child Class’ Construction script. I hope that helps.
Cheers,
runeberg
Hi,
I have also tried creating an UMaterialInstanceDynamic in the Constructor in C++. I had issues by using UMaterialInstanceDynamic::Create in the constructor and the solution of RuneBerg posted on May 20 '18 helped me.
But then I had troubles when I was realoading my world (When I quit Unreal studio and relaunched later my project). The MaterialInstanceDynamics were no longer there.
So, if anyone have the same issue, here is the solution that I found.
Don’t create the the material instance dynamic in the constructor at all. Put your code inside PostActorCreated(). That way, it’s like the MID is created outside the constructor and… well I don’t know why but that don’t create the same issues that it does in the constructor.
/// Header file
/**
* Called after the constructor.
* Used to create the material instance dynamic of the cables.
* Can't be create directly in the contructor because it will not be created again on the reload of the world.
*/
virtual void PostActorCreated() override;
/// Cpp file
void AITPowerSupplySystem::PostActorCreated()
{
UE_LOG(LogTemp, Warning, TEXT("[%s] PostActorCreated"), *this->GetName());
Super::PostActorCreated();
for (uint8 i = 0; i < this->NumberCables; i++)
{
if (this->PowerSupplySystemCables.IsValidIndex(i))
{
UCableComponent* Cable = this->PowerSupplySystemCables[i].Components.Cable;
const FString CableMaterialRef = TEXT("Material'/Game/Materials/M_Cable.M_Cable'");
UMaterialInterface* const CableMaterialFinder = LoadObject<UMaterialInterface>(Cable, *CableMaterialRef);
if (CableMaterialFinder)
{
Cable->SetMaterial(0, UMaterialInstanceDynamic::Create(CableMaterialFinder, Cable));
UE_LOG(LogTemp, Warning, TEXT("[%s] create Material name : %s"), *this->GetName(), *Cable->GetMaterial(0)->GetName());
}
else
{
UE_LOG(LogTemp, Error, TEXT("[%s] Impossible to find UMaterial : %s"), *this->GetName(), *CableMaterialRef);
}
}
}
}