Saving a playthrough
What a save carries and what it deliberately does not, the two load rules that are not configurable, and why the text is the artifact.
All documentation — Reference
Start here
Concepts
Authoring for a build
Playing a story
The generated assets and code
The plugin and sync
On this page
A save is two halves composed: the engine’s — where the player is, what they have taken, the rollback window — and the runtime’s, which is variables, the entity overlay, the spawned entity instances, visit counts and the random generator’s state.
The session’s Save produces one; Restore puts it back. Both are on the session and forwarded by the TaleShard Player component.
What Save gives you
A TaleShardPlaythroughSave struct with one pin that matters: Json, the save as text, exactly
as the engine wrote it — UTF-8, a fixed key order, one trailing newline. The text is the
artifact. Store it, and hand it back to Restore.
Save is refused, with the reason, when nothing has been presented yet or when the story is waiting
on a command. The session’s Get Pending Command Code lets you say cannot save during
startCombat rather than cannot save.
Where to put it
Two shapes, and the difference is whether the story is the only thing you save.
| Your game | Use |
|---|---|
| has nothing else to save | Save Story to Slot and Load Story from Slot on the TaleShard Story actor, or on its TaleShard Player component (Get Player). Each takes a slot name and a user index, and does the whole job in one node, below |
| wants the save-game object in hand | TaleShardSaveGame, a save-game object that carries one playthrough. Store keeps a save with the project id; Get Save hands it back to Restore; Has Save answers whether one is held |
| has its own save game | one string field holding the save’s Json, and the project id beside it |
The project id is there so a save is never restored into another story. Check it before offering a Continue button.
Save Story to Slot, Load Story from Slot
Save Story to Slot is Save, then a TaleShardSaveGame holding the save and the project id,
written to the slot. Load Story from Slot reads the slot and hands what it holds to Restore,
with the same report. Each answers false with the reason, and changes nothing, when:
| Node | Refuses when |
|---|---|
| Save Story to Slot | Save is refused, as above, or the slot cannot be written |
| Load Story from Slot | the slot is empty, holds no TaleShard playthrough, or holds a playthrough of another project’s story — or Restore refuses the text |
The project-id check is done for you here.
What a save carries
| Notes | |
|---|---|
| Position | board, node, and the call stack — how a save inside a sub-board resumes into its caller |
| History | the rollback window, oldest first. The last entry is where the player stands |
| Taken choices | one key per choice already taken — what marks an option as seen. Stored rather than derived, because it is derivable from neither the capped history nor from visit counts |
| Said lines | one key per line already said, least recently said first — what a list playing Least recently said and a row ticked Once read. Stored for the same reason: a line Next Line returned is in no moment at all. Each history entry also carries the said lines as they stood when it was drawn, so a restored moment shows the line it showed then. Absent from the text when nothing has been said |
| State | every variable, the entity overlay, every spawned instance, visit counts, the random generator |
| Language |
The rollback window is capped at fifty moments. That bounds the save, not the live session: a running playthrough’s transcript is every step; a reloaded one can step back fifty times and no further.
What a save deliberately does not carry
- The steps themselves. They are re-derived on load, so a save cannot go stale against an edited board.
- The roll-forward stack.
- Anything older than the fifty-moment window.
What a restore does
Restore is legal at any time, including while a command is in flight — anything pending is abandoned, and every in-flight completion goes stale.
The two rules that are not configurable
| Situation | What happens |
|---|---|
| A variable the save predates | takes its authored default |
| A variable the project no longer declares | dropped |
Neither is an option, and that is deliberate: two supported load behaviours would mean two sets of saves in the field.
Both are reported, because a silently defaulted variable makes “why is my gate false after loading?” unanswerable.
Spawned instances
Every instance the session spawned (Entity scripts and instances) is saved under its own id, with the id and the code of the entity it copies, and its overlay travels with the rest. A restore brings the instances back before the overlay and replaces every live one: an instance spawned after the save is gone, and one despawned after it is back. Its template is found by id first and by code second, as an overlay entry is. An instance whose template the project no longer has, or whose id an authored entity now holds, is dropped with its overlay and reported under Dropped Entities.
A playthrough that never spawned anything writes no instances key, so its save is byte for byte
the one it always was.
The report
Restore hands back a TaleShardSaveLoadReport: what the load had to change, so you can tell the
player.
| Pin | Notes |
|---|---|
| Dropped Moments | how many rollback moments were dropped because their node no longer exists — the back window is shorter than the save’s |
| Dropped Entities | overlays dropped because the entity is gone, and instances whose template is gone |
| Dropped Variables | codes the project no longer declares |
| Defaulted Variables | variables the save predates. Each took its authored default |
| Refused Values | values refused for exceeding the size budget |
| Is Clean | nothing was dropped or defaulted |
Is Clean is the one to branch on. Everything else is what you show when it is false.
Restore is refused outright, never partially applied, when the text cannot be read: empty, too long, unparseable, or a format version that is absent, older or newer. The reason names which.
What is not in a save
The engine’s language is. Your own game state is not, and neither is anything you keep outside the runtime: an inventory you modelled in your own Blueprints rather than as project variables is yours to persist, in the same save game, beside the story’s text.
The rule of thumb: if a script could write it, it is in the save. If only your code could, it is not.