It’s just a little question about something that kinda bugs me
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.
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 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.
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.