Crash diffing level with PCG component

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