Table of Contents
- The main issue: Unity serializes by field name
- What SOBackupRestore does (in one breath)
- When you should use it
- How it works (under the hood)
- Quick start (Editor workflow)
- Field-name remapping (optional but powerful)
- Best practices I follow alongside SOBackupRestore
- Limitations (know them, avoid surprises)
- Why JSON, not custom tooling?
- Closing thoughts
SOBackupRestore is an Editor-only utility for Unity that backs up and restores ScriptableObject
assets as GUID-named JSON files.
It mirrors the Inspector’s serialization (fields, lists, enums, nested data, and asset references) and can optionally remap field names (old → new) during restore, letting you refactor schemas and still push your values back into existing assets without touching your production pipeline.
The full, updated source code is available on GitHub under MIT license, meaning it can be used free of charge for any purpose.
I built SOBackupRestore because I was tired of watching carefully tuned ScriptableObject data vanish after harmless refactors—renaming a field, moving a class, shuffling namespaces. If you ship content-heavy games—or iterate aggressively—you’ve probably felt that pit-in-the-stomach moment: the code compiles, the Inspector looks fine… and your .asset
values are mysteriously gone.
In this article, I’ll show what SOBackupRestore
does and how to use it step by step to protect your data during refactors.
The main issue: Unity serializes by field name
Unity’s serializer keys off field names. Rename a [SerializeField]
(or change a type), and existing assets can no longer match the stored keys. Unity doesn’t know where to put that data, so it gets dropped from the Inspector.
Yes, there are great tools like [FormerlySerializedAs]
and [MovedFrom]
—and you should use them—but real projects get messy:
- You’re touching dozens of ScriptableObject types.
- Some fields change multiple times across sprints.
- Someone moved classes across assemblies/namespaces.
- You need a guaranteed way to roll forward after a schema change.
I wanted a toolbox wrench I could reach for any time I planned a risky refactor.
What SOBackupRestore does (in one breath)
SOBackupRestore is an Editor-only utility that:
- Backs up every ScriptableObject it finds into a pretty-printed JSON file.
- Names each file by the asset’s GUID (not by path), so moving/renaming assets is safe.
- Restores values into the existing assets via
EditorJsonUtility.FromJsonOverwrite
. - Optionally applies a simple field-name remap (oldKey → newKey) during restore, so you can survive aggressive renames even if you didn’t (or couldn’t) annotate everything with
[FormerlySerializedAs]
.
Result: You can refactor with confidence, then push your data back in.
When you should use it
- Before large refactors of ScriptableObject schemas.
- When merging content branches where field names diverged.
- As a lightweight migration step alongside
[FormerlySerializedAs]
/[MovedFrom]
. - When onboarding teammates who reorganize project folders and asset names.
It’s not a replacement for good hygiene—it’s a seatbelt that lets me move faster.
How it works (under the hood)
- Backup: For each ScriptableObject found under selected folders, the tool writes
{guid}.json
containing the exact Inspector-style serialization (lists, enums, nested data, references as{fileID, guid, type}
, even manySerializeReference
cases). - Restore: For each
*.json
, it resolves the GUID back to an asset path, loads the ScriptableObject, optionally rewrites field keys in the JSON (string replace on"fieldName":
), and callsFromJsonOverwrite
to populate values. Assets are marked dirty; nothing new is created.
Because everything is keyed by GUID, path shuffles won’t break the mapping.
Quick start (Editor workflow)
- Put the script in an Editor folder. Any
.../Editor/
path works (e.g.,Assets/Tools/Editor/SOBackupRestore.cs
). It must be Editor-only. - Backup: In the Project window, select the folders you want (or leave nothing selected to scan all of
Assets/
). Use the menu: Tools → Contrappasso → Backup ScriptableObjects to JSON…. Pick an output folder (I store backups outsideAssets/
). - Refactor: Rename fields/classes/namespaces freely. Add
[FormerlySerializedAs]
/[MovedFrom]
where feasible. - (Optional) Map field names: Open SOBackupRestore and fill the
keyRenames
dictionary (see below). - Restore: Tools → Contrappasso → Restore ScriptableObjects from JSON…. Point it to your backup folder. Watch values flow back into assets.
Tip: Commit before and after. The JSON makes great forensic breadcrumbs in code reviews.
Field-name remapping (optional but powerful)
Drop old → new mappings into a dictionary before restoring. The tool will rewrite JSON keys and then overwrite asset values.
1 2 3 4 5 6 7 8 9 |
// Put these inside SOBackupRestore's keyRenames dictionary before restoring // All code and comments in English var keyRenames = new Dictionary<string, string> { { "damage", "baseDamage" }, { "rangeMeters", "range" }, { "crit", "critChance" }, // Chain more as needed... }; |
This is a pragmatic safety valve when you can’t annotate every renamed field (e.g., cross-team churn, multiple legacy branches). It only rewrites JSON keys (the left-hand side of "key": value
), keeping values intact.
Best practices I follow alongside SOBackupRestore
- Keep .meta files visible and Force Text serialization (Project Settings → Editor).
- Prefer private serialized fields + public properties to reduce future renames of serialized names.
- Add
[FormerlySerializedAs]
on renamed fields and leave it in for a couple of releases. - Use
[MovedFrom]
when changing class names/namespaces/assemblies. - During big migrations, run a backup, then a restore, then open a few “sentinel” assets/scenes and eyeball the values.
Limitations (know them, avoid surprises)
- Only covers Unity-serializable data (public or
[SerializeField]
). Not static fields, not pure computed properties. - It overwrites values on existing assets; it doesn’t create new assets.
- If you change types incompatibly, Unity can’t deserialize old values. Use migration code (
ISerializationCallbackReceiver
) for real schema changes.
Why JSON, not custom tooling?
- JSON is transparent—diffable, greppable, easy to hot-fix.
EditorJsonUtility
mirrors what the Inspector does. No surprises, no custom formatter to maintain.- Backups can live outside your project tree, so they don’t contaminate builds or CI.
Closing thoughts
SOBackupRestore doesn’t make refactors trivial—but it removes the fear. I built it to move faster on Contrappasso without playing roulette with hours of tuning buried in ScriptableObjects. If you’re juggling lots of content and you iterate hard, give this workflow a spin. Combine it with good Serializer hygiene and you’ll sleep better the next time you rename damage
to baseDamage
five minutes before a milestone.
If you want, I can share a trimmed “starter” template (menu items + minimal UI) or a version that targets a specific type (e.g., WeaponData
only) and generates a before/after CSV for sanity checks.