State & Save¶
Capture and restore object state — positions, rotations, physics, UI — in topic-typed slices. Saving the whole scene to a file and loading it back comes with Magpile, through SceneState.
Overview¶
Need to reset an object to its starting position after a player dies? Want to save game progress to a file and load it back later? The State package handles both, at two levels:
- Per-object state via ObjectStateHolder and topic state holders — pick the slice you want to save (Transform, Rigidbody, GameObject, …) and add operations to it.
- Whole-scene saves via SceneState, which comes with Magpile — capture every registered scene object and pool-spawned instance, with cross-references resolved automatically and an optional async settle phase on restore.
Both layers are data-driven: configure what to save in the Inspector using class selection, and trigger save/restore through commands or SceneState's API.
Per-object state ships with every Jungle plugin. Without Magpile you can capture and restore objects in memory, for example to reset a level, but not write the scene to a file.
Topic-typed state holders¶
State is decomposed by topic — a topic holder targets a specific component type (or GameObject) and only accepts operations valid for that type. The structure mirrors Jungle's targeted commands: a TransformStateHolder works on a Transform and only accepts ITransformStateOperations, a RigidbodyStateHolder works on a Rigidbody and only accepts IRigidbodyStateOperations, and so on.
This means:
- The picker only shows operations relevant to the current topic — no scrolling through a flat list of every state class in the project.
- The target is resolved once on the holder (via a SmartX value), not per-operation.
- New aspects of an existing topic can be added simply by writing one more operation class implementing the topic's marker interface.
For the catalog of built-in topic holders and their operations, see Topic State Holders. Each holder picks its own target via its SmartX value — no parent composite is required.
ObjectStateHolder¶
The MonoBehaviour you drop on a saveable GameObject. It hosts a list of StateHolderBase entries — topic holders chosen per-aspect, each with its own smart target. See ObjectStateHolder for details.
ObjectStateHolder (component on a saveable GameObject)
├─ Holders:
│ ├─ Transform State
│ │ ├─ Target: SmartGameObject (Self by default)
│ │ └─ Operations: Position, Rotation
│ ├─ Rigidbody State
│ │ ├─ Target: SmartRigidbody (sibling by default)
│ │ └─ Operations: Velocity
│ └─ GameObject State
│ ├─ Target: GameObject (Self by default)
│ └─ Operations: Active
└─ Capture On Begin / End Action (optional automation)
Authoring a custom operation¶
Plugin authors implement one of the topic interfaces (ITransformStateOperation, IRigidbodyStateOperation, etc.) — typically by extending StateOperation<T>:
[Serializable]
[JungleClassInfo("Renderer Color", "Saves the renderer material color.", null, "Audio & Visuals")]
public class RendererColorStateOperation : StateOperation<Renderer>, IRendererStateOperation
{
[SerializeField, HideInInspector] private Color color;
protected override void OnCapture(Renderer t) => color = t.material.color;
protected override void OnRestore(Renderer t) => t.material.color = color;
}
The base class handles the HasCapturedData flag (so the state survives JSON round-trip) and gates Restore on it. Cross-references to other GameObjects go through SavedRef — the scene state encodes and decodes them transparently.
Commands¶
| Command | Description |
|---|---|
| Capture State | Calls CaptureAll() on the target Object State Holder. |
| Restore State | Calls RestoreAll() (optionally clearing afterwards). |
| Clear State | Calls ClearAll(). |
To save to a file, use Magpile's SceneState: the Scene State Command with Save To File and Load From File, or SaveToFile / RestoreFromFile from code.
Collision matrix¶
Magpile can also keep Unity's layer collision matrix (Project Settings > Physics). The Collision Matrix State holder saves and restores it, and the Apply Collision Matrix operation in the Physics Settings Command applies a matrix you set in the Inspector.
Practical Examples¶
Resettable Object¶
Save a transform on level start, restore it on death.
- Add ObjectStateHolder to the object.
- Add a Transform State entry. Inside it, add a Full operation.
- Set the holder's execution frame to your lifecycle (e.g.
Mono Lifecycle Frame: EnableDisable), enable Capture On Begin, set End Action to Restore And Clear.
The transform is captured automatically when the holder enables, restored when it disables.
Save the Whole Scene¶
For scenes mixing static GameObjects with pool-spawned items (typical for Octoputs scenes with attachment points + attachable pools). Needs Magpile.
- Drop a SceneState component in the scene.
- Register every persistent scene object in Permanent Refs (Key + GameObject) and every runtime pool/factory in Creators (Key + creator).
- Add an ObjectStateHolder to each saveable object (and each pool prefab) with the topic holders and operations you want.
- Optionally add settle conditions like Time Delay or Rigidbodies At Rest so restore waits for physics/animation before reporting done.
- Call
sceneState.SaveToFile(path)andsceneState.RestoreFromFile(path, onComplete)from your save UI or commands.
Cross-object references (e.g. "this AttachmentPoint was holding that AttachableObject") are handled by SavedRef inside individual operations — plugin authors put SavedRef fields in their operations, end users never see them.
Architecture¶
flowchart TD
subgraph SceneState
SS[Permanent Refs + Creators registries]
end
subgraph ObjectStateHolder
OSH[List of StateHolderBase]
end
subgraph "Topic Holders"
TH1[TransformStateHolder]
TH2[RigidbodyStateHolder]
TH3[GameObjectStateHolder]
THN[…]
end
subgraph Operations
OP1[ITransformStateOperation impls]
OP2[IRigidbodyStateOperation impls]
OP3[IGameObjectStateOperation impls]
end
SS -->|CaptureAll / RestoreAll| OSH
OSH --> TH1
OSH --> TH2
OSH --> TH3
OSH --> THN
TH1 --> OP1
TH2 --> OP2
TH3 --> OP3