Remember Prefab (SaveablePrefab)

1 What the component does

A Remember Prefab—class name SaveablePrefab—is Crystal Save’s Swiss-army knife for prefab persistence. Attach it to any prefab (enemy, UI panel, pick-up, etc.) and it automatically records everything a loader needs to respawn that object in exactly the same state:

  • ✔ Works for editor-placed, runtime-spawned, and pooled instances

  • ✔ Captures transforms, physics, animation, visibility, runtime edits, blendshapes, materials, added components, VFX timing and more

  • ✔ Plays nicely with higher-level utilities (Targeted Restore, Destroyed-Object Restore, etc.)


2 Requirements

  • Crystal Save Core

  • Crystal Save Settings installed

  • Optional: a Crystal Save-compatible object pool (e.g. SaveablePrefabPool) for high-frequency spawning


3 Installation & first-time setup

  1. Add the component Select your prefab asset → Add Component → Crystal Save / Prefabs / Remember Prefab.

  2. Hit Play, spawn the prefab or interact with it, then save

SaveManager.Instance.Save(1);
  1. Load it back:

SaveManager.Instance.Load(1, restoreLastActiveScene: true);

The prefab will reappear exactly as saved—position, active state, animation time, particle burst, etc.


4 Inspector reference

Section
Purpose

Keep Across Scenes

Makes the instance DontDestroyOnLoad so it follows the player through level loads.

Remember Home Scene

Restores the prefab only when its original scene is loaded.Automatically disables Keep Across Scenes and any Off-screen masks.

Visible in Scenes

List of scenes where the prefab remains active. Scenes not in the list trigger Off-screen behaviour.

Off-screen Deactivation

Bit-mask: disable Colliders, Renderers, Character Controller, set Rigidbody Kinematic while the prefab is off-screen or in another scene.

Register With Save System

Leave checked. Uncheck only for short-lived cosmetic objects. Pools set this automatically.

Unique ID / Prefab Asset ID (read-only)

Runtime GUID of the instance and stable GUID of the asset. Assigned automatically—never edit by hand.

Child Identification

Important ⚠️ – children are tracked by hierarchy path. If you rename or re-parent them at runtime add a RememberComposite + modules.

Tracking Toggles

Track Skinned Mesh OverridesTrack Material OverridesTrack Added ComponentsTrack Particle SnapshotsTrack Child State OverridesTrack Child Transform OverridesTrack Component BlobsEnable only what you need to keep save-files lean.

Apply Saved Component Data On Respawn

When this toggle is enabled, the save system will reapply every recorded ISaveable payload beneath the prefab each time the instance is respawned, even if that data has already been loaded once before. This is implemented by forcing the component manager to skip its “already deserialized” guard whenever it detects the prefab context flag during a restoration pass.

  • Turn it on for pooled or frequently destroyed/recreated prefabs that must always come back with their saved state (inventory contents, upgraded stats, quest progress, etc.).

  • Leave it off if your components only expect a single LoadData call per session—reloading them on every respawn can retrigger side effects, animations, or expensive initialization that you only wanted once.

Load Priority

Every SaveablePrefab carries a 0–100 priority value (default 50). During a load, immediate prefabs are sorted by this number so the highest priorities spawn first, ensuring mission-critical objects appear before less important set dressing.

  • Raise the priority for objects the player must see or interact with immediately (player avatars, quest givers, blocking doors).

  • Lower it for ambiance pieces or large batches of decorative props so they can load later without blocking gameplay.

Defer Until Requested

Setting “Defer Until Requested” pushes the prefab’s save entry into the deferred queue instead of restoring it during the main load batch. Deferred items stay staged (still sorted by priority) until a system such as PrefabManager.ProcessDeferredPrefabs(...) explicitly asks for them—ideal for streaming in remote areas or optional content.

  • Enable it for side rooms, encounter waves, or distant regions you plan to stream in after a trigger or proximity check.

  • Disable it if the prefab must always be present after load; forgetting to request a deferred prefab leaves it absent from the scene until asked.

Disable Pooling

Even when global pooling is active, this flag forces the prefab to use classic instantiate/destroy semantics. The factory and save pipeline check the component-level setting before consulting registry overrides, so opting out here always wins—handy when an object is unsafe to reuse or carries state that pooling cannot reset reliably.

  • Enable it for destructible objects, one-shot cinematics, or prefabs that spawn asynchronous children you cannot safely clean when returned to a pool.

  • Keep pooling for frequently spawned effects or enemies where the performance gain outweighs the extra cleanup logic.

Enable Performance Caching

When performance caching is active, the prefab registers itself—and its instance and asset identifiers—in static dictionaries while enabled. Systems that need to resolve a prefab by GameObject can then hit the cache instead of calling GetComponent repeatedly, trimming lookup overhead until the prefab is disabled or destroyed (at which point the entry is removed).

  • Turn it on if you have high-frequency lookups (AI targeting, HUD bindings, analytics) that repeatedly fetch the same prefab or IDs each frame.

  • Leave it off when memory is tight or the prefab spends most of its life disabled—maintaining the extra dictionaries for rarely accessed objects provides little benefit.

Enable Batch Registration

Batch registration tells the save manager to register the prefab’s whole subtree over multiple frames instead of doing it in one big synchronous walk. This reduces spikes when a prefab contains many Remember components, but the tooltip warns that order-sensitive setups can observe a one-frame delay until the next batch finishes.

  • Enable it for large structures, modular bases, or UI canvases whose many tracked children otherwise cause registration hitches.

  • Disable it if other systems expect the entire hierarchy to be registered immediately—especially when parent/child dependencies must be available in the same frame.


5 What gets saved & restored

Always Serialized

  • Transform – world position, rotation, local scale

  • Parent link – remembers scene-root vs nested + re-parents on load

  • Children – active/disabled/destroyed states

  • Rigidbody – velocity, angular velocity, drag, gravity, kinematic flag

  • Animator – current state hash + normalised time

  • VisibilityactiveSelf + Off-screen flags

  • Particle Systems – time & playing state

  • Runtime-added components – full binary snapshot

  • Mesh / Material overrides

  • Blendshape Weights

  • Colliders – enabled/trigger + shape data

Optional (per toggle)

Toggle
Adds

Track Skinned Mesh Overrides

Records sharedMesh changes on any MeshFilter / SkinnedMeshRenderer.

Track Material Overrides

Records per-slot material swaps.

Track Added Components

Serialises new components you add via code or visual scripting.

Track Particle Snapshots

Resumes particle sims mid-burst.

Track Child State / Transform Overrides

Persists child (de)activations, tag/layer changes, local position/rotation/scale edits.

Track Component Blobs

Stores arbitrary ISaveable payloads emitted by helper scripts.


6 How the save / load cycle works

  1. Saving

    • SaveablePrefab gathers the baseline (transform, visibility, physics…)

    • If a tracking toggle is on, it diffs the live object against the original prefab and serialises only the changes.

    • All bytes are wrapped in a SaveablePrefabData struct and stored in the slot file.

  2. Loading

    1. PrefabManager looks up prefabAssetID, instantiates the asset and injects uniqueID.

    2. Baseline data (transform, active state, visibility…) is applied.

    3. Runtime modifications are replayed (added components, mesh/material swaps, particles, child edits).

    4. Any ISaveable helpers living under the prefab receive their blobs.

    5. SaveManager.OnGameObjectRestored fires → gameplay code can respond.

Edge-cases handled automatically

  • Pools recreated after a load

  • Trigger colliders preserved

  • Destroyed objects stay destroyed


7 Instantiation & pooling

Simple runtime spawn

using Arawn.CrystalSave.Runtime;

public GameObject enemyPrefab;           // prefab *asset* with SaveablePrefab on it

void SpawnEnemy(Vector3 pos)
{
    SaveablePrefab enemy = SaveablePrefabFactory.Instantiate(
        prefabAsset: enemyPrefab,
        position: pos,
        rotation: Quaternion.identity
    );
}

Using a pool (obsolete since Version 1.6.20) - Pooling can now be enabled in the Save Settings

SaveablePrefabPool pool;

void Awake()
{
    pool = new SaveablePrefabPool(
        enemyPrefab.GetComponent<SaveablePrefab>(),
        initialSize: 10,
        rememberObjects: true     // pooled instances are still saved
    );
}

void Fire(Vector3 pos, Quaternion rot)
{
    var enemy = pool.Spawn(pos, rot);
}

The pool calls OnBeforeSpawn / OnBeforeDespawn so IDs are recycled cleanly and save-files never bloat.

8 Tips, limits & best-practices

✔ Do
✖ Don't

Keep tracking toggles minimal—enable only what your game needs.

Turn everything on “just in case” (larger save-files, longer load times).

Add RememberComposite aka Remember Component when you rename or re-parent children at runtime.

Rely on default path-based child tracking after renaming (IDs break).

Call SaveablePrefabFactory.Instantiate inside coroutines/tasks exactly like Unity’s Instantiate.

Mix factory & raw Instantiate on the same asset (hard to debug).

Treat SaveablePrefab aka Remember Prefab as one-stop persistence—no need for RememberGameObject on the same object.

Add both SaveablePrefab aka Remember Prefab and RememberGameObject (redundant).

9 Troubleshooting & FAQ

Question
Answer

The prefab clones share the same Unique ID – loads break.

Instead of using Object.Instantiate. Try it with SaveablePrefabFactory.Instantiate.

Children disappear after load.

Path-based IDs broke (rename / re-parent). Add RememberComposite + modules for those children.

My mesh / material swaps aren’t saved.

Enable Track Skinned Mesh Overrides / Track Material Overrides on the prefab.

Save-file size exploded.

Turn off tracking toggles you don’t need (particles, added components, blobs…).

Pooled objects never restore.

Ensure the pool exists before you load and that its root GameObject is active.

Destroyed instance comes back after load.

Make sure RememberDestroyed is true in GameObject Property Settings and the object actually registered its destruction (check console or Tools/Crystal Save/Runtime Debug/Crystal Save Debug Window).

Last updated