How Can I Access Project Materials From Code?

I have followed the Procedural Mesh Generation Tutorial (Good Stuff). Then Added UV Support as outlined in This Thread

I am generating simple quads. When I drag them out into the editor, or spawn them at runtime, I get the default checkerboard patten (which I assume is a good thing). But I cannot change the material that is used (drag and drop). Now I don’t really need the drag and drop functionality and I have been told that a simple “YourMeshComponent->SetMaterial(0,TheMaterial);” should do the trick. But I do not know how to access Materials from my project. Forgive me if this question has been answered already, I have searched Forums and AnswerHub to no avail.

Your first option would be to call this code in your constructor with the appropriate path for your material

static ConstructorHelpers::FObjectFinder<UMaterial> Material(TEXT("Material'/Game/Materials/YourMaterialName.YourMaterialName'"));

if(Material.Object != NULL)
{
    TheMaterial = (UMaterial*)Material.Object;
}

Then create a dynamic instance of that material

  TheMaterial_Dyn = UMaterialInstanceDynamic::Create(TheMaterial, this);

And finally setting the material like you have been doing

  YourMeshComponent->SetMaterial(0,TheMaterial_Dyn);

The second option would be to instead of finding the material in your project through the code in your constructor like above would be to use UPROPERTY for example

 UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Materials)
      UMaterial* TheMaterial;

If you have created a class blueprint for this current class then this is a more visual approach producing a Material variable in your blueprint where you can select any material within your project, just be sure to create a dynamic instance of the material which ever way you decide to do this so your materials can be changed at runtime.

1 Like

This works, however instead of using

  UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Materials)
       UMaterial* TheMaterial;

You should use

UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Default)
UMaterialInterface* TheMaterial;

so it will work with material instances ad well.

1 Like

Not work for me :frowning:

ConstructorHelpers::FObjectFinder<UMaterial> MaterialHandSpriteLoader(_T("Material'/Game/Widgets/Textures/Hand/MAT_3DIcon.MAT_3DIcon'"));
if (MaterialHandSpriteLoader.Succeeded())
{
	UMaterial* M = (UMaterial*)MaterialHandSpriteLoader.Object;
	UMaterialInstanceDynamic* MaterialInstance = UMaterialInstanceDynamic::Create(M, this); //<- Although compiled, the error is caused by this
}

Log:
Unknown exception - code 00000001
(first/second chance not available)

"Fatal error:
[File:D:\BuildFarm\buildmachine_++depot+UE4-Releases+4.10\Engine\Source\Runtime\CoreUObject\Private\UObject\UObjectGlobals.cpp]
[Line: 2646] NewObject with empty
name can’t be u

The code runs from the constructor of an Actor

yes me too. project crash.

I got it working by modifying this code:

=====

ConstructorHelpers::FObjectFinder MaterialHandSpriteLoader(_T(“Material’/Game/Widgets/Textures/Hand/MAT_3DIcon.MAT_3DIcon’”));

if (MaterialHandSpriteLoader.Succeeded())

{

 UMaterial* M = (UMaterial*)MaterialHandSpriteLoader.Object;

 UMaterialInstanceDynamic* MaterialInstance = UMaterialInstanceDynamic::Create(M, this); //<- Although compiled, the error is caused by this

}

===

To this:

ConstructorHelpers::FObjectFinder

MaterialHandSpriteLoader(_T(“Material’/Game/Widgets/Textures/Hand/MAT_3DIcon.MAT_3DIcon’”));

UMaterial* M = (UMaterial*)MaterialHandSpriteLoader.Object;

UMaterialInstanceDynamic* MaterialInstance = UMaterialInstanceDynamic::Create(M, this);

YourMeshNameHere->SetMaterial(0, M);

Your code example is messy. What did you change? For me the first line alone will crash.

Probably is because you are triying to Create the material in a class that is not inherited from an UObject (like AActor), so you can’t use “This”, because this is referred to an UObject.

You have to do something like:

this->SphereMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("SphereMesh"));

static ConstructorHelpers::FObjectFinder<UMaterial> Material(TEXT("Material'/Game/Materials/YourMaterialName.YourMaterialName'"));
 
 if(Material.Object != NULL)
 {
     TheMaterial = (UMaterial*)Material.Object;
 }

TheMaterial_Dyn = UMaterialInstanceDynamic::Create(TheMaterial, SphereMesh);

SphereMesh ->SetMaterial(0,TheMaterial_Dyn);

In my case, I succeeded to get Material in order to set material on my mesh. This is my source code.

in header file:

UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Defult")
	URuntimeMeshComponent* m_myMesh;

UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Defult")
	UMaterial* m_myMaterial;

in constructor on source code:

m_myMesh = CreateDefaultSubobject<URuntimeMeshComponent>(TEXT("My Mesh"));
static ConstructorHelpers::FObjectFinder<UMaterial> Material(TEXT("Material'/Game/Materials/YourMaterialName.YourMaterialName'"));
if (Material.Succeeded())
{
    m_myMaterial= MaterialObject.Object;
    m_myMesh->SetMaterial(0, m_myMaterial);
}

For those who meet compile error “cannot convert argument 1 from ‘T *’ to ‘UObject *’”

Import Runtime/Engine/Classes/Materials/Material.h in header list.