24
2026Dev Log 3: Making Unity Save Files More Reliable
Save systems look simple until players depend on them.Writing JSON to disk is easy. Keeping save data compatible, diagnosable, and recoverable after months of development is the harder part.
That is why LoL Engine’s save system became one of the most important production systems in the package.
The Baseline
LoL Engine includes a data persistence service with:
– Save slots
– Async save/load operations
– Compression and encryption support
– Auto-save and quick-save patterns
– Serialization helpers
– Save events
– Configurable save behavior
Those features are useful, but they are only the beginning. The changelog shows several rounds of hardening where real edge cases shaped the system.
Fixing the Hidden Serialization Problem
In 0.17.6-beta, a bug was fixed in the serializer contract resolver. Private Unity fields marked with [SerializeField] were not actually being included by Newtonsoft’s default member discovery.
That meant important fields such as checksum and version data could be missing from written save files. The load path could still proceed, but integrity warnings appeared because the data needed for validation had not round-tripped correctly.
The fix was to include private [SerializeField] fields through the type hierarchy and add a regression test proving the JSON contained the expected fields.
That is a good example of why save systems need tests that inspect the saved data, not only tests that call Save() and Load().
- Samples Included in LoLEngine
- SaveLoad Sample
- SaveLoad Sample – Saved File
Pluggable Save Storage
Version 0.21.0-beta added ISaveStore, a storage abstraction for save I/O.
The default implementation is LocalFileSaveStore, which uses local files and atomic write-via-temp behavior. There is also an InMemorySaveStore for integration tests.
This matters because the save system should not be welded to File.* calls. Once storage is abstracted, tests can exercise save/load behavior without touching disk, and future projects can route saves through different backends.
Per-Domain Schema Migration
The same release added per-domain schema versions and IDomainMigration.
A save file is rarely one blob of one kind of data. Player settings, inventory, world state, progression, and runtime systems may evolve at different speeds. If every change bumps one global save version, migration logic gets messy quickly.
LoL Engine lets each persistable domain declare its own schema version. When a save loads, the system can run migration chains for the specific domains that changed.
That keeps migration focused:
Inventory v1 -> v2
Settings v1 -> v2
Progression stays v1
Corrupt-File Quarantine
Another 0.21.0-beta feature was corrupt-file quarantine.
When a save fails because of JSON parse failure, checksum mismatch, or incompatible bundle schema, the save system moves the bad file into a quarantine folder instead of silently deleting it or leaving the player with no explanation.
In development, a quarantined file gives you something to inspect. In production support, it gives the player a chance to recover or send the file for diagnosis.
Load Reports
SaveLoadReport records what happened during load:
– Overall success or failure
– Quarantine reason when applicable
– Per-domain load results
– Stored and current schema versions
– Whether a migration ran
That turns “load failed” into useful information.
It also helps UI. A game can decide whether to show a generic failure message, a partial-load warning, or a migration notice.
Partial Success Instead of All-or-Nothing Failure
Version 0.22.0-beta hardened migration and deserialization failures so they are caught per domain. A failure in one domain no longer has to crash the entire load operation.
That is the kind of behavior players feel even if they never see the code. If one optional domain fails but the rest of the save can load, the system should preserve as much state as it safely can and report exactly what happened.
Why This Belongs in a Framework
Every serious Unity project needs save infrastructure, but most games should not spend their early development time rediscovering the same save-system failure modes.
LoL Engine’s save system tries to provide the boring parts:
– Version tracking
– Migration hooks
– Integrity checks
– Quarantine
– Reports
– Async operations
– Testable storage backends
Your game still owns its save data. The framework owns the mechanics around storing and recovering it.
LoL Engine will be available for Unity 6000.0+.
– Asset Store: TBD
– Documentation: TBD


