Correct way to show updates from value changes in editor?

I have a C++ class which extends USceneComponent and adds various other components/functionality. As part of the hierarchy, there are another two nested USceneComponents:


 - Root
 - - LocatorRoot
 - - - Locator

And there are two UPROPERTY’s that can be set in the editor:


UPROPERTY(EditAnywhere, BlueprintReadWrite)
FVector LocationOffset;

UPROPERTY(EditAnywhere, BlueprintReadWrite)
FRotator RotationOffset;

These properties drive the location/rotation of those SceneComponents using these two lines of code:


LocatorRoot->SetRelativeRotation(RotationOffset);
Locator->SetRelativeLocation(LocationOffset);

So I want the level designers to be able to change these properties in the editor (not in BeginPlay - it needs to be in the editor because it’s important to see how it looks), and the location/rotation values to be updated accordingly.

I understand that placing those two lines in the C++ constructor won’t pick up the changes made on a Blueprint in the editor, but I can’t figure out the correct way to get it working.

I tried:


void UNodeLocatorComponent::PostInitProperties()
{
    Super::PostInitProperties();

    LocatorRoot->SetRelativeRotation(RotationOffset);
    Locator->SetRelativeLocation(LocationOffset);
}

But it does nothing. I also tried:


void UNodeLocatorComponent::PostEditChangeProperty(FPropertyChangedEvent & PropertyChangedEvent)
{
    LocatorRoot->SetRelativeRotation(RotationOffset);
    Locator->SetRelativeLocation(LocationOffset);
}

But this crashed the editor for calling a pure function.

I would have just created a Blueprint version of the class (so that I could add the logic to the construction script) but when I right click on the C++ class in the editor, “Create C++ derived from NodeLocatorComponent” is not accessible, though I’m not sure why…?

So what is the correct way to this?

OK, so the reason PostEditChangeProperty was crashing the editor is because I forgot the WITH_EDITOR directive. But if I try this:


#if WITH_EDITOR
void UNodeLocatorComponent::PostEditChangeProperty(FPropertyChangedEvent & PropertyChangedEvent)
{
    UE_LOG(LogTemp, Warning, TEXT("%f"), LocationOffset.X);
    LocatorRoot->SetRelativeRotation(RotationOffset);
    Locator->SetRelativeLocation(LocationOffset);
}
#endif

When I change the values in the editor, the updated value for LocationOffset.X is being output to the Output Log, so this is obviously working and getting the correct value, BUT neither the SetRelativeRotation nor SetRelativeLocation are doing anything… so it still doesn’t work.

Try adding


Super::PostEditChangeProperty(PropertyChangedEvent);

either before or after your other code.

If that doesn’t help, then it’s probably an execution order thing, with your changes getting stomped on by the construction script and component recreation. Other possibility is to override OnRegister:



void UNodeLocatorComponent::OnRegister()
{
  Super::OnRegister();

  LocatorRoot->SetRelativeRotation(RotationOffset);
  Locator->SetRelativeLocation(LocationOffset);
}


The first one almost works - while I’m changing a value (by dragging on a number) it correctly updates, but the second I let go of changing the number it jumps back to default value.

However, OnRegister works perfectly - thanks so much!