s&box/field-guide
the symptom, in your words

"Save/load without drift"

✓ verified on engine 26.07lane: Writing gameplayposted
▸ SYMPTOM
  • Load places buildings slightly wrong, duplicates props, or skips ones that existed at save.
  • Old saves crash or silently zero important fields after you add properties.
  • You saved full tree positions instead of "which trees were chopped" and the file is huge / drifts from regen.
▸ CAUSE

Drift comes from two spawn paths (editor/bootstrap vs load) or from treating missing JSON as meaningful zeros. Static world should be deterministic; only deltas belong in the save.

▸ FIX

DTO + FileSystem.Data

snippet
var json = Json.Serialize(saveDto);
FileSystem.Data.WriteAllText("save.json", json);

if (FileSystem.Data.FileExists("save.json"))
{
    var loaded = Json.Deserialize<SaveDto>(FileSystem.Data.ReadAllText("save.json"));
}

Use Sandbox's Json.Serialize / Json.Deserialize<T>.

One spawn path

  1. Mark runtime-placed structures with a small component, e.g. PlacedBuildable { BuildId }.
  2. Save loop: read component state per GameObject into DTOs.
  3. Load loop: respawn through the same factory used for live building — no parallel "load-only" constructor.

Deterministic static world

Fixed RNG seed for trees/rocks/scatter. Save only deltas (chopped-tree indices, not every tree pose).

Schema evolution

Missing JSON fields → C# defaults. Guard restored values:

snippet
health = loaded.Health <= 0 ? 1f : loaded.Health;

Keep enums append-only (new values at the end). Autosave on a natural checkpoint (sleep / day boundary).

▸ WHY IT WORKS

One factory means load cannot invent a different collider/facing/scale than play. Deterministic regen shrinks the save to true deltas. Append-only enums + guarded defaults make old files load into new builds without treating "missing" as "zero forever."

Verified on engine 26.07 — seen in a real project.
s&box moves fast; an undated fix is a liability. Spot a stale detail?