Redundant serialization in the engine code.

Hey everyone,

It’s just a little question about something that kinda bugs me :slight_smile:

There’s something I don’t understand about the choice of serialization methods in the engine code and I have this feeling that I am missing something. For example, let’s take a look at the ULevel::Serialize in the 4.17 branch and look for this code:

    Ar << URL;

    Ar << Model;

    Ar << ModelComponents;

If we then take a look at the declaration of these properties we’ll see that URL is not a U-property so it’s completely clear why it is serialized manually, however, Model and ModelComponents are actually U-properties and they are not transient so they must be serialized by SerializeScriptProperties in UObject so it is not quite clear (at least for me) why should they be serialized for the second time in Serialize function.

Maybe you know, @DarkVeil ? :slight_smile:

They are not serialized a second time. Once you’re specifying a Serialize() function, you’re overriding automatic serialization with custom serialization code. The main reason that many classes have custom serialization functions is for backward compatibility. If you take a closer look at ULevel::Serialize, you’ll see that there are different code paths taken depending on CustomVer and UE4Ver, and whether the object is being loaded or saved.

I’m with Robert in not following this. The override calls Super::Serialize, which would serialize those two properties in the regular way, no?

@gmpreussner ? :slight_smile:

I also have this question. UObject::Serialize eventually calls UObject::SerializeScriptProperties which, as I suppose, is responsible for UProperty serialization.

If you don’t ‘feed’ the FArchive with the picked properties ( << operator) then serialier function won’t know about these properties… AFAIK the system iterates the FArchive data for serialization and not the actual fields of the UObject.

> The override calls Super::Serialize, which would serialize those two properties in the regular way, no?

Ah, I missed the super call. I think you’re right. UObject will go through all non-transient script properties. I’ll check with our Core guys.

This does, indeed, seem to be a bug. Perhaps those fields were once variables, but later converted to properties. That code is quite old though, so it’s been that way forever. Does it cause any problems for your particular use cases?

No, it doesn’t cause any problems, in fact. I was just interested if there’s any reason to serialize properties twice like that when writing my own custom serialization code. If I understand correctly, any manually serialized property should be marked as transient.

By the way, are there reasons to use custom serialization others than backward compatibility? Storing data in a more efficient way perhaps? Would it actually be faster at the cost of user-friendliness as it doesn’t involve property name lookup?

Just to add a bit of salt into the conversation, I use custom serialization to mainly optimize data and to have pre-calculated values that I use in run-time, so that’s one of the reasons to use your own serialization.