This library allows you to programatically update all assets in your project when the structure of your serialized fields change.
Regardless of where those assets are found within your asset database (prefabs, prefab variants, scenes, or scriptable objects), the reserialization will be applied to them, allowing you to programmatically update the shape of your objects.
public class SomeClass : MonoBehaviour
{
[Obsolete] public int someField;
public bool newField;
[MenuItem("Tools/Reserialize the class")] // Run this snippet from the Unity Editor
public static void Reserialize()
{
Reserializer.Reserialize<SomeClass>(ctx =>
{
ctx.Instance.newField = ctx.Instance.someField == 1;
});
}
}The callback receives a rich ReserializeContext<T> providing full information about the object being reserialized:
| Member | Description |
|---|---|
ctx.Instance |
The target instance being reserialized. |
ctx.GetPathToInstance() / ctx.PropertyPath |
Unity property path to this instance (e.g. items.Array.data[0].nestedData). |
ctx.GetNearestEngineObject() |
Nearest UnityEngine.Object owning this field (the Component or ScriptableObject). |
ctx.GetRootEngineObject() |
Root GameObject (for prefab/scene) or ScriptableObject. |
ctx.GameObject |
Containing GameObject (if in a component). |
ctx.Component |
Containing Component (if in a component). |
ctx.AssetPath |
Asset path on disk (e.g. Assets/Prefabs/Player.prefab). |
ctx.ScenePath |
Scene path (if serialized in a scene). |
ctx.IsSerializedInAScene() |
true if the instance is located inside a scene. |
ctx.IsSerializedInARootPrefab() |
true if the instance is located in a base/root prefab. |
ctx.IsSerializedInAVariantPrefab() |
true if the instance is located in a prefab variant. |
ctx.IsSerializedInScriptableObject() |
true if the instance is located in a ScriptableObject. |
ctx.IsPrefab |
true if in any prefab (root or variant). |
ctx.IsPropertyOverriddenInVariant() |
true if this property has an override modification in a prefab variant. |
ctx.GetSerializedObject() |
Lazily gets the SerializedObject for the nearest engine object. |
ctx.GetSerializedProperty() |
Lazily gets the SerializedProperty for this instance. |
ctx.WriteBack() |
Writes value-type (struct) mutations back to the parent hierarchy. |
When implementing your migration delegate, make sure that it is idempotent. Reserialization runs on root prefabs first and then on prefab variants in dependency order.
You can also check ctx.IsPropertyOverriddenInVariant() to determine whether a prefab variant actually modified a property or inherited it from the base prefab:
Reserializer.Reserialize<SomeNestedData>(ctx =>
{
if (ctx.IsSerializedInAVariantPrefab() && !ctx.IsPropertyOverriddenInVariant())
{
// Inherited from base prefab (which was already migrated) - do not assign unnecessarily
return;
}
ctx.Instance.newValue = ctx.Instance.oldValue + 1;
});