Download

Implement UPROPERTY in C++

I have this on a header file:



UPROPERTY(EditAnywhere)
	FLinearColor* EmiterColor;

And I want to do update this VectorParameterValue when I change property *EmiterColor. Something like this:


StarMaterialInstanceDynamic->SetVectorParameterValue(FName(TEXT("EmiterColor")), newValue);

But my problem is that I don’t know how to ‘connect’ the property with the code above.

Now, I’m setting that value here:



void AStarActor::PostInitializeComponents()
{
	Super::PostInitializeComponents();

	StarMaterialInstanceDynamic = UMaterialInstanceDynamic::Create(StarMaterial, this);

	StarMaterialInstanceDynamic->SetVectorParameterValue(FName(TEXT("BaseColor")), FLinearColor(FMath::VRand()));
	StarMaterialInstanceDynamic->SetVectorParameterValue(FName(TEXT("EmiterColor")), FLinearColor(FMath::VRand()));

	SphereVisual->SetMaterial(0, StarMaterialInstanceDynamic);
}


In other words, I want to enable change EmiterColor in Unreal Editor. How can I do it?

I’m very new on Unreal development.

Is the problem that it’s not updating when you change the value? You might want to use PostEditChangeProperty if you want it to live update in the editor. If that’s not your problem, I’m not certain what you’re looking for/what’s not working.

Yes, that is the problem. I don’t know how to ‘connect’ the property with the code that will change that VectorParameterValue.

Ok, I did it:


#if WITH_EDITOR  
void AStarActor::PostEditChangeProperty(struct FPropertyChangedEvent& e)
{
	Super::PostEditChangeProperty(e);

	FName PropertyName = (e.Property != NULL) ? e.Property->GetFName() : NAME_None;
	if (PropertyName == GET_MEMBER_NAME_CHECKED(AStarActor, EmiterColor))
	{
		if (StarMaterialInstanceDynamic)
			/* Because you are inside the class, you should see the value already changed */
			StarMaterialInstanceDynamic->SetVectorParameterValue(FName(TEXT("EmiterColor")), EmiterColor);		
	}
}
#endif

But StarMaterialInstanceDynamic is always null. Any idea about how can I instance it? On Editor I can’t set any material instance to it.

Is StarMaterialInstanceDynamic defined anywhere? It seems like you haven’t created and initialized the right variables yet.

I’ve done what you’re trying to do, lemme paste some example code. In this instance “Material” is a pre-created base material named “GameMaterial” with parameters in it.

In your class definition in the header file:


UPROPERTY(EditAnywhere) UMaterial * Material;
UPROPERTY(EditAnywhere) UMaterialInstanceDynamic * MaterialInstance;

In your cpp file:


AGameActor::AGameActor(const class FObjectInitializer& FObjectInitializer) : Super(FObjectInitializer)
{
    GameMesh = FObjectInitializer.CreateDefaultSubobject<UStaticMeshComponent>(this, TEXT("GameMesh"));
    RootComponent = GameMesh;


    ConstructorHelpers::FObjectFinder<UMaterial> MatFinder(TEXT("Material'/Game/Game/GameMaterial'"));
    if (MatFinder.Succeeded()) {
        Material = MatFinder.Object;
        MaterialInstance = UMaterialInstanceDynamic::Create(Material, Package);
    }


}

When you want to update a parameter:


void AGameActor::SetGameMaterialParameter(FName ParameterName, UTexture * Texture) {
    UE_LOG(LogTemp, Warning, TEXT("[Game] Setting material for %s"), *ParameterName.ToString());
    MaterialInstance->SetTextureParameterValue(ParameterName, Texture);


}

I’ve left out the code for assigning the material to the mesh as I don’t have it on hand (I’m using UMaterialInstanceConstant for a different reason, which does everything differently. Go figure.) This code also assumes you’re assigning a staticmesh via code, so you can chop that bit out if you like too.

Anyway, I’m sure you know about writing to object properties in C++, eg. mygameobject->color = FColor::Red;

The UPROPERTY() part above means several things:

  1. The type after it inherits from the UObject class at some point
  2. It’s exposed to the user interface in the editor (if you click a spawned actor of this type, this member will appear in the list in the details panel)
  3. It’s memory-managed by UE after that, anything referenced by that UPROPERTY() won’t be destroyed until the actor doing the referencing no longer exists. This is a Very Good Thing.
  4. It can be accessible by blueprints (with the right arguments in UPROPERTY())

So it’s not JUST for blueprints but most of what it does is to do with blueprints and the UI, but it has its place even if you’re just doing C++. I recently solved a stack overflow by inheriting my classes from UObject and letting them be managed by UE.

You can do all of the above in blueprints too, by getting an actor, getting its mesh, getting its material, creating a dynamic material instance and hooking it up then setting parameter values. In fact, I did this in blueprints first to work it out and then moved it to C++.