Setting Material and Material Instance In c++ Without Crashing

I’m in the process of converting some of my blueprints to code and I keep hitting this problem. Maybe I’m missing something obvious but it causes the engine to crash when the code should be changing the material.

this is what I’m trying to achieve

125411-temp.jpg

.cpp

.h

125399-temp.jpg

and this is the error i get from it

Hey Djekko,

I see a couple things that I would change in my code:

First, after doing FObjectFinder, you need to check if the search for the object succeeded. For example, if I was looking for ShaderMat, I’d do

if(ShaderMat.Succeeded())
{

}

Here is the full code that I used to set up a dynamic material instance on a static mesh in an actor class.

MyActor.h:

#include "GameFramework/Actor.h"
#include "MyActor.generated.h"

UCLASS()
class MATTEST_API AMyActor : public AActor
{
	GENERATED_BODY()
	
public:	
	// Sets default values for this actor's properties
	AMyActor();

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

	UStaticMeshComponent* MeshComp;

	UMaterial* StoredMaterial;

	UMaterialInstanceDynamic* DynamicMaterialInst;

	
	
};

MyActor.cpp

#include "MatTest.h"
#include "MyActor.h"


// Sets default values
AMyActor::AMyActor()
{
 	// 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;

	MeshComp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh"));

	static ConstructorHelpers::FObjectFinder<UStaticMesh> FoundMesh(TEXT("/Engine/EditorMeshes/EditorSphere.EditorSphere"));
	if (FoundMesh.Succeeded())
	{
		MeshComp->SetStaticMesh(FoundMesh.Object);
	}

	static ConstructorHelpers::FObjectFinder<UMaterial> FoundMaterial(TEXT("/Engine/VREditor/BasicMeshes/M_Floor_01.M_Floor_01"));
	if (FoundMaterial.Succeeded())
	{
		StoredMaterial = FoundMaterial.Object;
	}
	DynamicMaterialInst = UMaterialInstanceDynamic::Create(StoredMaterial, MeshComp);

	MeshComp->SetMaterial(0, DynamicMaterialInst);

}

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

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

}

Doing this seemed to work perfectly on my end.

Let me know if that helps or if you need any clarification/explanation.

Have a great day!

1 Like

Thanks for a quick reply

This makes complete sense and I’ve now implemented it in but I still have the engine crashing.

this is my code now.

This makes complete sense and I’ve now implemented it in but I still have the engine crashing.

this is my code now.

static ConstructorHelpers::FObjectFinder<UMaterial> FoundMaterial(TEXT("/Game/ChronosTests/BlackHole/VFX/Materials/M_VolumeSphereMaster2"));
			if (FoundMaterial.Succeeded())
			{
				ShaderMaterial = FoundMaterial.Object;
			}
			ShaderMatInst = UMaterialInstanceDynamic::Create(ShaderMaterial, MeshComp);

			OtherComp->SetMaterial(0, ShaderMatInst);

the header files also match yours with the change in names of corse.

Im getting this when th eengine crashes now and dont know what to make fo it.

Fatal error: [File:D:\Build++UE4+Release-4.12+Compile\Sync\Engine\Source\Runtime\CoreUObject\Private\UObject\UObjectGlobals.cpp] [Line: 3088]
FObjectFinders can’t be used outside of constructors to find /Game/ChronosTests/BlackHole/VFX/Materials/M_VolumeSphereMaster2

The only other thing that i can make out that could be causing an issue is that im trying to set a material on a primative component not a static mesh component as the component is determained by an overlap event. Ive had a quick look at seeing if i can change a primitive component to a static mesh component but have no luck.

Any Suggestions?

If you’ll notice, in your crash error message:

“FObjectFinders can’t be used outside of constructors”. Basically what’s happening is you’re trying to use FObjectFinder outside of your actor’s constructor, which you can’t do. You’ll need to implement this inside of the constructor as I have. You can still assign it later, post construction, but you’ll need to actually find the object in the constructor itself. This should resolve the crash.

It works

It’s obvious when you explained it back, It’s been a long day.

Thanks for the quick replies :slight_smile: