Why does this not work (crashes editor)?

Been a while since I used UE

In constructor of AActor derived class:

Works:

Material_Instance = UMaterialInstanceDynamic::Create(Material_Dynamic, nullptr);

Doesn’t work:

Material_Instance = UMaterialInstanceDynamic::Create(Material_Dynamic, this);

I feel like using “this” worked before or do I misremember?

I’m not exactly clear on the circumstances but using a pointer to the object itself (in this case AActor) will cause a crash if used in its own constructor with Create function. I assume because the object is not fully created yet so it cannot be used as an outer for new material.

You are safe to use this pointer outside of the constructor as an outer for creating material, or even better in PostInitializeComponents(). If you don’t need to serialize this material and still want to create it in constructor you can try use GetTransientPackage() instead of this pointer.

if you look inside the create function you can see


UMaterialInstanceDynamic* UMaterialInstanceDynamic::Create(UMaterialInterface* ParentMaterial, UObject* InOuter)
{
	LLM_SCOPE(ELLMTag::MaterialInstance);
	UObject* Outer = InOuter ? InOuter : GetTransientPackage();
	UMaterialInstanceDynamic* MID = NewObject<UMaterialInstanceDynamic>(Outer);
	MID->InitializeMID(ParentMaterial);
	return MID;
}

Notice it invokes the NewObject command. NewObject can’t be used in a constructor only once the object exists (so in beginplay).

Sure you can put nullptr but then it has no outer (parent) internally, so it exists in a void. The only way to salvage it would be to set the outer at a later point in time (outer is private and only has a GetOuter() function)

In short it’s breaking ground rules set by Epic. Use it outside of the constructor.