The class `UPCGComponent` has a member variable, `FPCGSelectionKeyToSettingsMap DynamicallyTrackedKeysToSettings`, which is not a UProperty but is custom serialized. This is a map with key type `FPCGSelectionKey`. This key type uses `UStruct::SerializeTaggedProperties` in its serialization, which cannot be used with archive types that use custom property list:
checkf(!UnderlyingArchive.ArUseCustomPropertyList,
TEXT("Custom property lists only work with binary serialization, not tagged property serialization. "
"Attempted for struct '%s' and archive '%s'. "), *GetFName().ToString(), *UnderlyingArchive.GetArchiveName());
However, diffing levels in the editor uses `FJsonStringifyArchive` to display the level data as JSON, and this archive does have `ArUseCustomPropertyList` set to true. So attempting to serialize `FPCGSelectionKey` with it fails the check.
Steps to Reproduce
Unfortunately I am not familiar enough with PCG to provide a standalone repro.
If you have a level with an actor with a PCGComponent that has some data in `DynamicallyTrackedKeysToSettings` trying to diff that level (against anything) crashes the editor.
Hi Javier, thanks for reaching out.
We’ll have a look!
Cheers,
Julien
Hi Javier,
Thanks for your patience, but I had a look into it.
What happens is that when doing the diff, it goes through a json serializer, and that’s not using (or allowing) the use of serializing tagged properties (which we always do for the PCG selection keys).
I think we’ll refactor this in the future (could have been serialized as an array instead of a map, would have been fine then), but a workaround right now is this change - just the if here is sufficient to side-step the crash.
FArchive& operator<<(FArchive& Ar, FPCGSelectionKey& Key)
{
// The JSON object-graph stringify archive (used for text/JSON level diffing) runs with a
// null custom property list to suppress reflected-property serialization. Tagged-property
// serialization asserts in that mode (see UStruct::SerializeVersionedTaggedProperties).
// This archive only emits text and never round-trips through the linker, so returning early
// here does not affect the binary on-disk format or the export SerialSize.
if (Ar.ArUseCustomPropertyList)
{
return Ar;
}
Hope this helps,
Cheers,
Julien