Best practices for asset versioning

What are Epic’s practices for non-trivial transformations of asset data that may occur through the course of development? The engine supports trivial changes like deleting or adding a UPROPERTY, but what about more involved changes?

Case 1: Renaming a property without data loss.

Case 2: Custom data transformation.

The canonical simple example is having three separate UPROPERTY float values that you wish to be combined into a single UPROPERTY FVector. You could imagine far more complex and arbitrary transformations.

How would I make that change to a class that may be instantiated by hundreds of uasset files, without destroying the existing data?

In other engines I’ve worked on, it was possible to retain an “old version” class layout and provide a custom transformation function. I’m not sure if Unreal provides a facility like that.

For renaming or performing a transformation, we usually do this in a 2 phase process. The first phase is to mark the old UPROPERTYs as deprecated and add the new property that is to replace them. Then in PostLoad() you copy the data in the case of a rename or transform it in the case of 3 floats to a FVector. Once you have that in place, you run the ResavePackages commandlet to upgrade all of the data. Phase 2: you can safely delete the deprecated UPROPERTYs without data loss.

For native serialization, we use the Archive version information to fix the data up. There are tons of examples in the source for this. Search for things like

if (Ar.IsLoading() && Ar.Ver()