Save slots
How slots are named, laid out on disk, listed cheaply and moved between machines with export and adopt.
A slot is a directory#
Every slot is a directory under the save root, with its own primary file, its own backups and its own revision sequence:
Application.persistentDataPath/
nexusforge/<product namespace>/<environment>/
slots/
default/primary.nfsav
slot-03/primary.nfsav
autosave/primary.nfsav
checkpoint-0001/primary.nfsavBecause a slot owns its backups, a bad write in one slot can never cost you another one.
Naming rules#
A slot name must be safe as a path segment, so SaveSlotId applies one rule to every identifier in the package:
^[a-z0-9]([a-z0-9._-]*[a-z0-9])?$That single rule removes path traversal, Windows device-name collisions, trailing-dot aliasing and case-sensitivity differences between platforms. Slot ids are also capped by Limits.MaxIdentifierLength (64 by default).
var slot = new SaveSlotId(class="tok-str">"slot-03"); // throws if the name is unsafe
if (!SaveSlotId.TryCreate(playerTypedName, out var fromInput))
{
ShowErrorToPlayer(class="tok-str">"That name cannot be used for a save slot.");
}Use TryCreate whenever the name originates outside your code.
Listing slots without reading saves#
A "Continue" menu should cost kilobytes, not megabytes, so listings read the header and metadata only:
var slots = await NexusForgePersistence.Slots.ListAsync();
var info = await NexusForgePersistence.Slots.InfoAsync(new SaveSlotId(class="tok-str">"slot-03"));
foreach (var descriptor in slots.Value)
{
AddRow(descriptor.Slot, descriptor.Metadata.ModifiedUtc, descriptor.BackupCount);
}Metadata can include your own display values (a chapter name, a playtime, a level), which is what makes a slot list readable without decrypting anything.
Moving a save between machines#
var exported = await NexusForgePersistence.Slots.ExportAsync(slot, destinationPath);
var adopted = await NexusForgePersistence.Slots.AdoptAsync(sourcePath, slot);AdoptAsync validates the file before accepting it, so importing cannot drop an unverified or foreign file into your save root. Both calls go through the same integrity and envelope checks a load would.
Deleting#
await NexusForgePersistence.Slots.DeleteAsync(slot);Deletion is explicit and permanent for that slot. The framework never deletes a slot on its own — not on shutdown, not on disposal, not on reset. Disposal only stops work.
Next#
- Configuration reference —
BackupRetentionCount, path ceilings and limits. - Save and load — the full slot service surface.
- Save Browser — every slot, with actions, in the Editor.
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