Reading about the difference between UMaterialInterface, UMaterial, and UMaterialInstance it sounds like UMaterialInstance is the ideal choice if I just want to re-use an existing material with potentially different parameters. However, if I use the following architecture in my C++ class:
Header:
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
...
#include "SpellBullet.generated.h"
UCLASS(ClassGroup = "Combat", Blueprintable, BlueprintType, meta = (DisplayName = "SpellBullet", BlueprintSpawnableComponent))
class RYDDELMYST_API ASpellBullet : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor properties
ASpellBullet();
...
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Collision)
UHitBoxerComponent* HitBoxer;
// Projectile particle FX
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Projectile)
UNiagaraSystem* BulletParticles;
// Projectile material
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Projectile)
UMaterialInterface* BulletMaterial;
...
};
SpellBullet.cpp:
ASpellBullet::ASpellBullet()
{
...
// material setup if defined in editor
if (BulletMaterial)
{
BulletMesh->SetMaterial(0, BulletMaterial);
}
}
and the subclass BlasterBolt.cpp:
ABlasterBolt::ABlasterBolt()
{
...
// default material setup if not defined in editor
if (!BulletMaterial)
{
static ConstructorHelpers::FObjectFinder<UMaterial> Material(TEXT("'/Game/Ryddelmyst_Assets/Materials/M_GlowyPurpleLava.M_GlowyPurpleLava'"));
if (Material.Succeeded())
{
BulletMaterial = UMaterialInstanceDynamic::Create(Material.Object, BulletMesh);
BulletMesh->SetMaterial(0, BulletMaterial);
}
else
{
UE_LOG(LogTemp, Error, TEXT("BlasterBolt ctor; failed to load default glowy purple lava material asset"));
}
}
}
but then I get the following error trying to save a Blueprint derivative of that class:
Can't save ...NewBlueprint.uasset: Graph is linked to external private object MaterialInstanceEditorOnlyData /Script/Ryddelmyst.Default__BlasterBolt:BlasterBoltMeshComponent.MaterialInstanceDynamic_0.MaterialInstanceDynamic_0EditorOnlyData (EditorOnlyData)
The default material reads in the editor as MaterialInstanceDynamic_0, which certainly doesn’t seem correct. If I override that with a material selected from content browser the error on save goes away. How should I use/create UMaterialInstanceDynamic* in C++ so that I can have a default material that is overridable in Blueprints via the editor?