Material Color set in C++ class but not in blueprint class

I’m currently working on a small game idea that involves shooting projectiles that change color when they hit a wall.

I’m doing this project in C++, but created a blueprint instance to have more control over the meshes and all and i discovered something weird: If my character spawns the C++ class projectile, it successfully changes color, but if i instead spawn the blueprint that inherits from that class, it won’t change color!

I don’t know why this happens so I’m reporting it as a bug…

This is the code on my projectile C++ class constructor:

static ConstructorHelpers::FObjectFinder<UStaticMesh> StaticMeshAsset(TEXT("StaticMesh'/Game/StarterContent/Shapes/Shape_Sphere.Shape_Sphere'"));
static ConstructorHelpers::FObjectFinder<UMaterialInterface> MaterialAsset(TEXT("Material'/Game/StarterContent/Materials/M_Basic_Wall.M_Basic_Wall'"));
if (MaterialAsset.Object && StaticMeshAsset.Object)
{
	ProjectileMesh->SetStaticMesh(StaticMeshAsset.Object);
	ProjectileMID = ProjectileMesh->CreateDynamicMaterialInstance(0, MaterialAsset.Object);
	ProjectileMesh->SetMaterial(0, ProjectileMID);
}

NeutralColor = FColor::Yellow;
AllyColor_1 = FColor::Green;
AllyColor_2 = FColor::Blue;
FoeColor_1 = FColor::Red;
FoeColor_2 = FColor::Black;

ChangeMaterialColor(NeutralColor);

This is the code that i use to spawn the C++ version of the class (that successfully changes color):

FActorSpawnParameters SpawnParams;
SpawnParams.Instigator = Cast<APawn>(this);
ACodeBounceBallProjectile* Projectile = World->SpawnActor<ACodeBounceBallProjectile>(ACodeBounceBallProjectile::StaticClass(), SpawnLocation, SpawnRotation, SpawnParams);

This is the code i use to spawn the blueprint version of the class (which does not change color at all, i’m using the base material and its color remains white, screenshot in the next comment):

static ConstructorHelpers::FObjectFinder<UBlueprint> ProjectileBP(TEXT("Blueprint'/Game/FirstPersonBP/Blueprints/MyBounceBallProjectile.MyBounceBallProjectile'"));
if (ProjectileBP.Object) {
	ProjectileClass = (UClass*)ProjectileBP.Object;
}

/////////////////////////////////////////

ACodeBounceBallProjectile* Projectile = World->SpawnActor<ACodeBounceBallProjectile>(ProjectileClass , SpawnLocation, SpawnRotation, SpawnParams);

Can someone explain to me what’s going on?

Hey goncasmage-

I’m trying to setup a sample test on my end but I’m not sure exactly how ProjectileMID is used or what ChangeMaterialColor() is doing. Can you provide the full class for your projectile? Additionally, other than the constructor where is ChangeMaterialColor() being called?

ProjectileMID is a (UMaterialInstanceDynamic *) and is set in the constructor of the class.

ChangeMaterialColor(FColor NewColor) changes the projectileMID color using the SetVectorParameterValue(“DiffuseColor”, NewColor).

Hey goncasmage-

I was not able to use your class directly due to references to project specific code, however I did manage to setup a sample case that works:

I first created a “projectile color” material with a base color parameter. Then in my projectile class, I added an FLinearColor variable as well as a UMaterialInstanceDynamic and UMaterial pointer. In the constructor of my projectile class, I used a ConstructorHelper to get a reference to the material and set that to my UMaterial pointer.

static ConstructorHelpers::FObjectFinder<UMaterial> MaterialGet(TEXT("Material'/Game/FirstPersonCPP/Blueprints/ProjectileColor.ProjectileColor'"));

if (MaterialGet.Succeeded())
{
	MaterialRef = MaterialGet.Object;
}

I then used my static mesh component to set my material instance dynamic pointer.

CodeMID = MyStaticMeshComp->CreateDynamicMaterialInstance(0, MaterialRef);

On tick, I find a random number for the R, G, B, and A values of my FLinearColor

LinearColorProp.R = FMath::FRand();
LinearColorProp.G = FMath::FRand();
LinearColorProp.B = FMath::FRand();
LinearColorProp.A = FMath::FRand();

In My hit function I can then use the material instance dynamice pointer to set the parameter value of the Material

CodeMID->SetVectorParameterValue(FName("MyColor"), LinearColorProp);

1 - Are you spawning the class or the blueprint?

2 - That’s already what i did with a few minor changes that i applied in my project but produced the same result.

This setup works both when spawning an instance of my projectile blueprint as well as an instance of the projectile class itself.

Do the UMaterial and UMaterialInstanceDynamic variables have to be protected or does it make no difference?

Rather than saying it makes no difference, it would depend how they are being referenced. If they are marked as protected, they are only visible to the class that they’re defined in and child classes. In my setup test I left them public in order to have access to them anywhere.