Having trouble getting instanced objects in viewport to execute blueprint code on updates.

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;
}