Autosave

Debounce, ceiling, minimum interval, coalescing and pause flush — the numbers that decide when an autosave happens, and what it costs per frame.

Core features NexusForge Persistence 0.2.0 Updated

Dirty tracking, not polling#

Autosave is driven by change, not by a timer. Something meaningful happens, the game says so, and the coordinator decides when the write is due:

csharp
var autosave = new AutosaveCoordinator(
    options.Autosave,
    new DelegateSaveStateSource((slot, reason, token) => Slots.SaveAsync(slot, model, request, token)),
    context.Clock,
    context.Sequences);

autosave.MarkDirty(AutosaveReason.Milestone);   // when something meaningful changed

autosave.Tick(TimeSpan.FromSeconds(Time.unscaledDeltaTime));   // once per frame; it decides

Tick does not capture, serialise or write. It accumulates time and decides. Measured cost for an idle game: 0.03 ms per frame, which is what makes calling it from Update reasonable. Verified

The four numbers#

SettingDefaultWhat it means
DebounceDelay2 sHow long the game must stay unchanged before a write starts.
MaximumDelayBeforeSave60 sThe longest the oldest unsaved change may wait, however busy the game is.
MinimumIntervalBetweenWrites10 sBounds how often storage is touched.
SaveOnPauseRequestedtrueTreat "the app is being paused" as a reason to write.

AutosaveOptions.SlotId defaults to autosave, so autosaves never overwrite a player's manual save.

Why it does not stutter the game#

  1. One write at a time. A burst of changes coalesces into a single save; a second save while one is running is superseded rather than queued up behind it.
  2. Work off the main thread. Autosave asks the dispatcher for a capture on the main thread, then saves the snapshot on a worker. It never reads a Unity object from a worker thread.
  3. Failure is a result. A failed autosave does not throw into a frame; it is reported, and the game keeps running with its previous save intact.

Defining "meaningful" in your game#

AutosaveReason exists so a save can say why it happened, which shows up in metadata and diagnostics: Manual, Interval, ExitRequested, SceneBoundary, FocusLost, Milestone, Checkpoint, External.

csharp
class="tok-com">// A checkpoint reached, a boss defeated, a chapter closed — these are milestones.
autosave.MarkDirty(AutosaveReason.Milestone);

Next#

Something wrong on this page? Every page here describes behaviour that is checked in the repository. If a page and the package disagree, the package wins.

Report a documentation problem · Frequently asked questions · Troubleshooting