We’ve had an issue for a long time: sometimes we save the player pawn BP, close Unreal, and when we reopen Unreal and open the BP, the components appear empty in the Details panel. Then, when we run the game in the editor, we get crashes because those components are null.
After investigating further, the components created in C++ in the constructor of our Pawn-derived class are actually created correctly. CreateDefaultSubobject returns a valid component, which we store in a UPROPERTY variable so it can be edited in the editor. However, at some point this variable gets reset to null.
This seems to happen in UBlueprintGeneratedClass::InitPropertiesFromCustomList, which calls FObjectProperty::CopyValuesInternal and appears to overwrite the variable with its default value.
The only ways we’ve found to fix this are either renaming the variable (but then we lose all the modifications made to it in the editor), or reverting the BP to a previous version from Perforce.
I’ve attached a screenshot of the callstack at the moment when the variable gets reset.
Hey Marius, once a pointer to a default subobject (components, instanced objects) gets overwritten to null during initial loading of the blueprint, it’s likely that the asset has been saved with the value as null during a previous editor session. The thing to investigate is when exactly the UPROPERTY component reference becomes null for the first time.
A known cause that comes to mind is if the blueprint was created by duplicating another blueprint: known as UE-81109 and UE-273844. You filled in that you’re on UE 5.6, so that bug fix should already be in your engine version. Can you double-check if this code is merged in? Github link to fix. I believe your scenario isn’t from duplicating another blueprint, since you mention you can revert to a previous file version that works, but I want to bring it up just in case you find it relevant.
I wrote this guide to investigate blueprint data loss issues. What I recommend is putting checks (assertions) in your game code and engine code to find out at the earliest opportunity when a UPROPERTY() pointing to a component unexpectedly becomes null. For example, for the player pawn’s C++ class, override UObject::PreSave() to assert if the component reference is null so that people don’t save and check in a corrupted blueprint. UObject::PreSave is still pretty late. The chart in the linked guide could be helpful to add earlier checks. We will want to narrow down whether the value breaks on:
When the player pawn BP is compiled
When the parent BP is compiled and its values are propagated to derived BPs (if the player pawn BP derives from another BP).
When the player pawn BP is created by duplicating another BP (fixed in 5.6, but already broken assets stay broken)
Any other moment
“The only ways we’ve found to fix this are …”
Next time you problem that component references get nulled on load, you can consider a temp fix like this:
In your pawn’s AMyPawn::PostInitProperties() override
If the component reference is null
Call ForEachObjectWithOuter to find the component back, restore the reference
Resave the asset
If losing the component reference was the only problem, then this might un-break your asset. However, reverting is still the safest bet, since more data loss might have occurred that you haven’t found out yet.
Hello, yes I confirm that I do have the code fix from commit 75d047f.
No, this BP does not inherit from another BP but directly from a C++ class.
So I overrode the functions PostInitializeComponents, PostLoad, PostEditChangeProperty, and PreSave to add a component check and put a breakpoint in them in order to see at what moment it happens.