Blueprint failed serialization on circular classes (4.7+)

So simply blueprints of classes can cause ordering issues on serialization.

Example: make 2 object classes

ClassA

uproperty
TArray< TSubclassOf > BClasses;

ClassB

uproperty
TArray< TSubclassOf > AClasses;

Create a blueprint of A & B. Have Ab → Bb. Now create a child of Ab (Ab_Child - at this point properly has B reference). Now set Bb to point to both Ab and Ab_Child. Save all 3 and reopen editor.

Right click and load Ab_Child. The serialization flow will be erroneous and regenerate the class of the child WHILE serializing Ab (this is indicated by Ab_Child NOT having a reference to Bb while its parent still does, indicating a critical inheritance issue).

What happens in code is this:

  1. Ab_Child when right clicked triggers a preload on its parent Ab
  2. Ab triggers Bb to preload
  3. Bb triggers preload/createexport on Ab_Child via serialization
  4. Ab_Child serialization triggers Ab_Child class blueprint to Regenerate
  5. RegenerateBluePrintClass triggers CopyPropertiesForUnrelatedObjects of Ab TO Ab_Child and you are now screwed cause Ab is still inside of its “UObjectProperty::SerializeItem” not even finished with its own preload

Weird bug but based on it results I consider it somewhat critical to how blueprints are serialized, indicating a loophole that is hard to track down.

So a work around that may simply be all that is needed is in createexport to triggers a force load of the template before “LoadClass->GetDefaultObject();”

Basically

if (Template)
{
	auto Linker = Template->GetLinker();
	if (Linker && !Template->HasAnyFlags(RF_LoadCompleted))
	{
		Template->SetFlags(RF_NeedLoad);
		Linker->Preload(Template);
	}
}

LoadClass->GetDefaultObject();

Seemed to solve the cases I could find…

Hi ,

Sorry for the delay in responding to your post. I just tried to reproduce this issue in 4.7 preview 8, but was unable to see the results that you described. Would you be able to provide some additional information? Here is what I did:

  • Made two Actor classes (Classes derived from Object by default are not Blueprintable. Did you modify yours to make them Blueprintable?)

  • Added the following code to ClassA’s header file (and corresponding code to ClassB’s header file):

    UPROPERTY()
    TArray<TSubclassOf> BClasses;

  • Built the project in Visual Studio with the Editor closed (to eliminate Hot Reloading from the repro).

  • Created a Blueprint from each class: ClassA_BP and ClassB_BP

  • In ClassA_BP, added a variable of type ClassB_BP.

  • Created a child of ClassA_BP: ClassA_BP_Child

  • Verified that ClassA_BP_Child can access the ClassB_BP variable inherited from ClassA_BP.

  • In ClassB_BP, added a variable of type ClassA_BP and a variable of type ClassA_BP_Child.

  • Saved everything and closed the Editor.

  • Re-opened the project in the Editor.

  • Opened the ClassA_BP_Child Blueprint and verified that it still has access to the ClassB_BP variable inherited from ClassA_BP.

Where do your steps to reproduce this issue differ from mine? Could you clarify what you mean when you say “Right click and load Ab_Child?” I checked with a few others here and no one was sure exactly what you meant by that phrase.

Are you still able to reproduce this issue in 4.7 preview 8?