# Custom memories

A **Memory** captures one aspect of a game object's state through the [Remember](../../../manual/save-load/remember.md) component. Use one to save a Unity or third-party component that your code doesn't own.

## A Memory has two classes

The outer class captures state, while a nested `Data` class restores the captured values:

```cs
using System;
using UnityEngine;
using VisualScript.Icons;
using VisualScript.Runtime;

[Title("Rigidbody")]
[Image(typeof(IconPhysics), ColorTheme.Type.TextLight)]

[Serializable]
public class MemoryRigidbody : Memory
{
    [Serializable]
    public class Data : Memory.Data
    {
        [SerializeField] private Vector3 m_Velocity;
        [SerializeField] private Vector3 m_AngularVelocity;

        public Data()
        { }

        public Data(Rigidbody body)
        {
            this.m_Velocity = body.linearVelocity;
            this.m_AngularVelocity = body.angularVelocity;
        }

        public override Awaitable OnLoad(GameObject gameObject)
        {
            Rigidbody body = gameObject.Get<Rigidbody>();
            if (body != null)
            {
                body.linearVelocity = this.m_Velocity;
                body.angularVelocity = this.m_AngularVelocity;
            }

            return AwaitableUtils.DontAwait;
        }
    }

    protected override string Title => "Rigidbody";

    public override Memory.Data OnSave(GameObject gameObject)
    {
        Rigidbody body = gameObject.Get<Rigidbody>();
        return body != null ? new Data(body) : new Data();
    }
}
```

After Unity compiles the file, **Rigidbody** appears in the **Remember** component's memory dropdown. `OnSave` captures linear and angular velocity, and `Data.OnLoad` restores them when the game object still has a `Rigidbody`.

## The Data class

Everything the memory needs to restore state goes in `Data`, and it must be serializable by Unity.

!!! warning "Data must be self-contained"
    The save system writes `Data` to disk and reads it back in a future session. Values that depend on the original runtime state won't identify the same objects afterward. These include live object references, coroutines, and indices into runtime lists.

    Store values, IDs, and names. Resolve them back to live objects in `OnLoad`.

A parameterless constructor is required for deserialization.

## OnLoad is asynchronous

`OnLoad` returns an `Awaitable`, so a Memory can wait for a scene or asset to load, or for a system to become ready.

Return `AwaitableUtils.DontAwait` when the work is synchronous, which is the common case.

## Defensive restoring

The object being restored may differ from the saved version. A component may have been removed, the prefab may have changed, or the save may come from an older release. Handle those cases when restoring state:

- Null-check every component you fetch.
- Leave existing state unchanged when saved data is missing.
- Check that indices and counts are still valid before using them.

A Memory that throws during load aborts the load. Prefer leaving one property unchanged when its source component or data is missing.

## Cost

Every Memory adds to the save file and to load time. Save the minimum that reproduces the state:

| Save | Don't save |
| :--- | :--- |
| Values that gameplay changed | Values that never change |
| State that can't be recomputed | Anything derivable from other saved state |
| IDs and names | Live references |

## Memory or ISaveLoad?

Choose based on who owns the component and whether designers should opt into saving it:

| Write a | When |
| :--- | :--- |
| **Memory** | The state lives on a component you don't own, or should be opt-in per object. |
| **[ISaveLoad](isaveload.md)** | It's your own component or asset and should always save itself. |

A designer adds a Memory to a **Remember** component. A type implementing `ISaveLoad` controls its own registration, so it can participate without that per-object setup.

## Checklist

- `[Serializable]` on both the memory and its `Data`.
- `Data` holds only serializable, session-independent values.
- `Data` has a parameterless constructor.
- `OnLoad` null-checks and never throws.
- `Title` returns a readable dropdown label.

## Where to go next

- **[ISaveLoad](isaveload.md)** — save your own components and assets directly.
- **[Memories](../../../manual/save-load/memories.md)** — inspect the built-in set and designer workflow.
- **[Save lifecycle](index.md#the-save-cycle)** — place Memory capture and restoration in the full operation order.
