Editor crashes when creating UMaterialInstanceDynamic

The snippet of code below comes mainly from the procedural mesh generation wiki article, but I’ve attempted to assign a very simple default material to it, which instantly crashes the editor (when I recompile, and when I load the editor). No error message or information is presented.

The exact line it crashes at is 18, when the new instance is created.

The code I’ve been working with (entire class, based on default actor template):

// Fill out your copyright notice in the Description page of Project Settings.

#include "MeshTestGame.h"
#include "GeneratedCubeActor.h"
#include "ProceduralMeshComponent.h"


// Sets default values
AGeneratedCubeActor::AGeneratedCubeActor()
{
 	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

	// Find mat
	static ConstructorHelpers::FObjectFinder<UMaterial> Material(TEXT("Material'/Game/wood_mat.wood_mat'"));
	UE_LOG(LogTemp, Warning, TEXT("Material pointer: 0x%X"), Material.Object); // Prints 0x43507580

	auto matinstance = UMaterialInstanceDynamic::Create(Material.Object, this); // At this point the Editor crashes without any message or info.

	USphereComponent* SphereComponent = CreateDefaultSubobject<USphereComponent>(TEXT("RootComponent"));
	RootComponent = SphereComponent;

	UProceduralMeshComponent* mesh = CreateDefaultSubobject<UProceduralMeshComponent>(TEXT("GeneratedMesh"));

	TArray<FVector> vertices;
	vertices.Add(FVector(0, 0, 0));
	vertices.Add(FVector(0, 100, 0));
	vertices.Add(FVector(0, 100, 100));
	vertices.Add(FVector(0, 0, 100));

	TArray<int32> Triangles;
	Triangles.Add(0);
	Triangles.Add(1);
	Triangles.Add(2);

	Triangles.Add(0);
	Triangles.Add(2);
	Triangles.Add(3);

	TArray<FVector> normals;
	normals.Add(FVector(1, 0, 0));
	normals.Add(FVector(1, 0, 0));
	normals.Add(FVector(1, 0, 0));
	normals.Add(FVector(1, 0, 0));

	TArray<FVector2D> UV0;
	UV0.Add(FVector2D(0, 0));
	UV0.Add(FVector2D(0, 1));
	UV0.Add(FVector2D(1, 1));
	UV0.Add(FVector2D(1, 0));

	TArray<FColor> vertexColors;
	vertexColors.Add(FColor(100, 100, 100, 100));
	vertexColors.Add(FColor(100, 100, 100, 100));
	vertexColors.Add(FColor(100, 100, 100, 100));
	vertexColors.Add(FColor(100, 100, 100, 100));

	TArray<FProcMeshTangent> tangents;
	tangents.Add(FProcMeshTangent(1, 1, 1));
	tangents.Add(FProcMeshTangent(1, 1, 1));
	tangents.Add(FProcMeshTangent(1, 1, 1));
	tangents.Add(FProcMeshTangent(1, 1, 1));


	mesh->CreateMeshSection(1, vertices, Triangles, normals, UV0, vertexColors, tangents, false);
	mesh->CreateAndSetMaterialInstanceDynamicFromMaterial(0, matinstance);

	mesh->AttachTo(RootComponent);
}

// Called when the game starts or when spawned
void AGeneratedCubeActor::BeginPlay()
{
	Super::BeginPlay();
	
}

// Called every frame
void AGeneratedCubeActor::Tick( float DeltaTime )
{
	Super::Tick( DeltaTime );

}

I managed to fix the issue by changing line 18 to auto matinstance = UMaterialInstanceDynamic::Create(Material.Object, Material.Object);, but it still doesn’t render the material sadly.

1 Like

Nevermind, changing the material index from 0 to 1 fixed it… :slight_smile:

Hello ,

I’m glad to hear that you were able to solve the issue. If you run into any more problems involving this, please let me know.

You can also use (Material.Object, this) as you did in the beginning, if you call that outside of the constructor. the constructor you define in C++ pretty much runs for the CDO (class default object), while other instances just use copy-constructor and get the CDO as feed for copy.

It pretty much means that you need to create dynamic material instances outside of constructor, for example in PostInitProperties(), OnConstruction(), BeginPlay()… All of these run for each instance. I really advice to check out this link for better explanation: Actor Lifecycle | Unreal Engine Documentation

1 Like

that actually did the trick
problem is - if object, bound to UMaterialInstanceDynamic in one moment gets deleted for some reason - engine will crash immediately.
So bind to UMaterialInstanceDynamic something that will have same live cycle.
this was my problem, i used GetWorld() to bind material instance.

MIDynamicOverride = UMaterialInstanceDynamic::Create(MaterialAsset, GetWorld());

and every time when i closed Unreal Editor - it was crashing with this reasons:

crashRHIResources.h Resource is being deleted.
assertion failed Resource is being deleted

so how i fix that? I just bound UMaterialInstanceDynamic livetime to the material pointer liverime.
My pointer has smart type, it’s not “weak”.

TObjectPtr<UMaterialInstance> MaterialAsset;

So it will be deleted or garbage collected after all of it’s dependencies.
If we use it like so:

MIDynamicOverride = UMaterialInstanceDynamic::Create(MaterialAsset, MaterialAsset);
SMesh->SetMaterial(0, MIDynamicOverride);

It won’t crash.
Also putting this might work if your current object has longer livetime than material iinstance bound to it. In my case this dosen’t work, since int’s component, but if you creating UMaterialInstanceDynamic in the ACharacter, might work:

MIDynamicOverride = UMaterialInstanceDynamic::Create(MaterialAsset, this);