I was able to get it working by moving all the code into C++ and overloading these three UObject methods:
#if WITH_EDITOR
virtual void PostEditChangeProperty(struct FPropertyChangedEvent& InChangeEvent) override;
virtual void PostCDOCompiled(const FPostCDOCompiledContext& Context) override;
virtual void PostTransacted(const FTransactionObjectEvent& TransactionEvent) override;
#endif // WITH_EDITOR
And in the body of each one, I would perform my update before calling super:
UpdateWeaponColor();
Super::PostEditChangeProperty(InChangeEvent);
Also, FWIW, in my UpdateWeaponColor
will always create the DynamicMaterialInstance if it’s not present, so it looks like this:
void UTP_WeaponComponent::UpdateWeaponColor()
{
auto dynamicMaterial = GetDynamicMaterialInstance();
DJ_RETURN_IF(dynamicMaterial == nullptr);
dynamicMaterial->SetVectorParameterValue(FName("BodyColor"), WeaponColor);
}
UMaterialInstanceDynamic* UTP_WeaponComponent::GetDynamicMaterialInstance()
{
if (__dynamicMaterialInstance)
{
return __dynamicMaterialInstance;
}
if (__dynamicMaterialInstance = CreateDynamicMaterialInstance(0))
{
DJLog(Warning, "Generated DynamicMaterialInstance");
}
else {
DJLog(Warning, "Failed to generate DynamicMaterialInstance");
}
return __dynamicMaterialInstance;
}