Blueprint data loss in inherited components (UInheritableComponentHandler) when recompiling a child actor class

Assuming the UActorComponent you created as part of the repro steps is named UTestComponent.

As far as I can tell, the flow behind this data loss is:

  1. FBlueprintCompilationManageImpl::FlushCompilationQueueImpl creates a FBlueprintCompileReinstancer, and its constructor calls FBlueprintCompileReinstancer::MoveCDOToNewClass. which duplicates the UBlueprintGeneratedClass. The UBlueprintGeneratedClass::InheritableComponentHandler is duplicated, but the UTestComponent template that it stores as one of its `Records` is not, because of the comment on `KismetReinstanceUtilities.cpp:2055`, where any RF_ArchetypeObject owned by the class are moved temporarily to the transient package and renamed.
  2. In the following call stack: FBlueprintCompilationManageImpl::FlushCompilationQueueImpl -> FKismetCompilerContext::CompileClassLayout -> UInheritableComponentHandler::ValidateTemplates, the template for UTestComponent is invalidated, and renamed, this also affects the template in the duplicated REINST class (as this object was NOT duplicated in 1.)
  3. When the actor in level is rebuilt, FComponentInstanceDataCache::ApplyToActor is called, but FActorComponentInstanceData::MatchesComponent fails when restoring the custom value to the component variable, because its name is something like TestComponent_SOMENUMBER, instead of TestComponent_GEN_VARIABLE.
  4. Data is lost

EDIT: Looks like this doesn’t occur immediately, but at some point when ValidateTemplates happens, there is an old template still outer’ed to the transient package (with flag RF_MirroredGarbage) which prevents the template from getting the same correct name (TestComponent_GEN_VARIABLE), which kicks off the whole bug.

I’ve also tried calling ValidateTEmplates() on the duplicate class, but it immediately empties the UInheritableComponentsHandler::Records array because all the templates have the wrong (non-REINST) owner class (although this *does* fix the bug, and those records seem to get regenerated correctly anyways)

Steps to Reproduce
Create a UActorComponent class (blueprint or c++), add a variable to it, and add it to a new blueprint Actor class, and then create a blueprint subclass of that actor. Place an actor of the subclass into the level, and modify the value of the variable on the component. When you recompile the subclass, this value on the actor will be reset to the default value.

Hi,

I was able to reproduce this on 5.4.4, but that being said it has been fixed on 5.5!

I believe this is the public issue tracker, Unreal Engine Issues and Bug Tracker (UE\-219732), which indicates has been fixed on commit 36088801.

Please let me know if this helps, or if you have any other questions.

Regards

Thanks for that info, I didn’t come across that issue searching the bug list. Any way I can correlate that changelist number 36088801 to a commit on the publicly available github for backporting?

Unfortunately I couldn’t view the changelist number as it was restricted, but I did find this commit by the same person on that day that looks to be similar at: https://github.com/EpicGames/UnrealEngine/commit/cfe3d90e5528f56d5c19f186539899d0d3052fb5

or Commit cfe3d90; Fix potential data loss of changed properties on placed components of a derived blueprint class that does not modify the component

If this commit isn’t what you’re looking for I’ll go ahead and push this case up to Epic so they can provide more information on the fix.

As for correlating changelist numbers to a commit, I don’t think there’s a direct way unless the commit comment contains the CL number.

Thank you!