I’m facing a problem with the UMaterialInstanceDynamic in a Widget.
I have a widget taking a UMaterialInstance* as an argument and create a UMaterialInstanceDynamic in the Construct.
After a period of time, the referenced ParentMaterial is apparently deleted by the garbage collector.
The class :
class KSGM_API SKBatteryWidget : public SImage
{
public:
SLATE_BEGIN_ARGS(SKBatteryWidget)
:
..........
{}
/** @brief The HUD used to create the dynamic material instance. */
SLATE_ARGUMENT(AKPlayerHUD*, HUD)
/** @brief The fill material instance. */
SLATE_ARGUMENT(UMaterialInstance*, FillMatInst)
...
UMaterialInstanceDynamic* FillMatInstDyn;
....
}
In the construct :
void SKBatteryWidget::Construct(const FArguments& InArgs)
{
// Create the dynamic material instance
if (InArgs._HUD != nullptr && InArgs._FillMatInst != nullptr)
FillMatInstDyn = UMaterialInstanceDynamic::Create(InArgs._FillMatInst, InArgs._HUD);
.....
SImage::Construct(SImage::FArguments()
.Image(InArgs._BatteryBrush)
);
}
The InArgs._FillMatInst is a pointer coming from a widget style
USTRUCT()
struct KSGM_API FKActionBarStyle : public FSlateWidgetStyle
{
GENERATED_USTRUCT_BODY()
.....
/** @brief The energy fill material instance. */
UPROPERTY(EditAnywhere, Category = "Appearance")
UMaterialInstance* EnergyFillMaterial;
FKActionBarStyle& SetEnergyFillMaterial(UMaterialInstance* InEnergyFillMaterial) { EnergyFillMaterial = InEnergyFillMaterial; return *this; }
.....
}
The problem is in fact the UMaterialInstanceDynamic::Create is setting the pointer using MID->SetParentInternal
Which means, if the UMaterialInstance is destroyed, it becomes invalid.
-
UMaterialInstance (Name=Invalid) UMaterialInstance
-
UMaterialInterface (Name=Invalid) UMaterialInterface -
PhysMaterial 0xdddddddddddddddd (Name={ComparisonIndex=??? DisplayIndex=??? Number=??? }) UPhysicalMaterial * -
Parent 0xdddddddddddddddd (Name={ComparisonIndex=??? DisplayIndex=??? Number=??? }) UMaterialInterface * UMaterialInstanceDynamic* UMaterialInstanceDynamic::Create(UMaterialInterface* ParentMaterial, UObject* InOuter) { UObject* Outer = InOuter ? InOuter : GetTransientPackage(); UMaterialInstanceDynamic* MID = NewObject<UMaterialInstanceDynamic>(Outer); MID->SetParentInternal(ParentMaterial, false); return MID; }
First, I don’t know why the UMaterialInstance coming from the widget style is destroyed after a period of time ?
Second, do I have to make a copy of the UMaterialInstance and using the copy in UMaterialInstanceDynamic::Create ?
Third, How to avoid the UMaterialInstance, coming from the widget style, to be destroyed ?
Txs for your help,
D.