Hi,
I’m creating it in a setup function.
void UYagUIImage::SetupYagUIImage(FUIStyleStruct TargetUIStyleStruc, UWorld* ThisWorld)
{
if (!ThisWorld) return;
if (!ThisWorld->GetFirstPlayerController()) return;
//if (!TexturesParentMaterial) TexturesParentMaterial = LoadObject<UMaterialInterface>(NULL, TEXT("/Game/Yag/UI/White/Mat_PNG_HUD"));
//if (!TexturesParentMaterial) return;
if (!TextureImageMaterialInstance) TextureImageMaterialInstance = UMaterialInstanceDynamic::Create(TexturesParentMaterial, this);
if (!TextureImageMaterialInstance) return;
SetBrushFromMaterial(TextureImageMaterialInstance);
SetFrontTexture(ImageFrontTexture);
TextureImageMaterialInstance->SetScalarParameterValue(FName("FrontOpacity"), 1.f);
TextureImageMaterialInstance->SetVectorParameterValue(FName("FrontColor"), TargetUIStyleStruc.YagFontColor);
TextureImageMaterialInstance->SetScalarParameterValue(FName("BGOpacity"), 1.f);
TextureImageMaterialInstance->SetVectorParameterValue(FName("BGColor"), TargetUIStyleStruc.YagBorderBackgroundColor);
//TextureImageMaterialInstance->SetScalarParameterValue(FName("BGVignetteRadius"), .68f);
TextureImageMaterialInstance->SetScalarParameterValue(FName("BGVignetteRadius"), 1.f);
}
The parent material (TexturesParentMaterial) is currently created in the constructor, but i get the same error when creating it in the function (the commented code).
The whole idea is to allow the user to choose a custom UI skin through a structure FUIStyleStruct that contains various colors/opacities and other UI skin related parameters.
If i understood correctly the GC is creating a tree of safe objects (the root set) and the material instance is not part of it.
My custom image is created aside from this root set (hence it is classified as a "disregard for GC "object).
So my current understanding is that a “disregard for GC” object (my image) is referencing an object (the mat inst) that is outside the safe zone of CG (the root set) and could be deleted anytime, which creates a risk of crash as the image would reference a non-existant object.
I thought declaring the mat inst as a UPROPERTY() would do it but it doesn’t help.
So the current logic behind my code is to try to attach the material instance to an object belonging to the safe zone (GC root set) through the outer.
To complicate things, UWidget::GetWorld() seems to always return a nullptr, hence the UWorld parameter, to try things with the “real” UWorld.
And i’m confused about what is created in the editor and what is not (is there a world in the editor ? is there a player controller ?).
I tried various things with no success
UMaterialInstanceDynamic::Create(TexturesParentMaterial, this);
UMaterialInstanceDynamic::Create(TexturesParentMaterial, GetWorld());
UMaterialInstanceDynamic::Create(TexturesParentMaterial, ThisWorld);
UMaterialInstanceDynamic::Create(TexturesParentMaterial, ThisWorld->GetFirstPlayerController());
So all in all, after spending a lot of time trying to understand what’s going on and making a lot of tests, i’m left in complete confusion because:
- i’m not even sure i correctly understand my problem
- i don’t know what is and isn’t in the GC root set
- I read on the net that since 4.25 the slate UI element are not treated by GC like other UObjects
Hence this post.
Cedric