# Save custom classes with Remember CustomComponent

### 1 What the component does

Created for non-coding Game Designers, RememberCustomComponents is a generic SaveableComponent that scans your GameObject for custom MonoBehaviours (i.e. anything not part of UnityEngine or Crystal Save’s own helpers) and captures a snapshot of their serializable fields at save-time, then re-applies those values on load, adding missing components if necessary.

<figure><img src="https://166712561-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fp47l4hoFKIHGBwL1Cm4D%2Fuploads%2FAmOTUfxmqJXMSZPCEKv2%2Fimage.png?alt=media&#x26;token=03aa2491-a631-4dbc-a842-94137ef3106b" alt=""><figcaption></figcaption></figure>

### 2 Requirements

* Crystal Save Core
* Crystal Save Settings present

### 3 Installation & first-time setup

1. Select the GameObject whose custom components you wish to persist.
2. Add Component → Crystal Save / Remember Component
3. Add through the Remember Component the Remember Custom Component
4. Enter Play mode, exercise your custom component (modify its fields), then call:

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

Or make use of Tools/Crystal Save/Runtime Debug/Manage Save Slots and click the save button and then the load button.

You should see your MonoBehaviour fields restored exactly as they were.

### 4 Inspector reference

```csharp
[SerializeField, HideInInspector]
private SerializationMode mode = SerializationMode.AllCustomComponents;
// If SelectedComponents mode, you’ll see a mask-field for picking specific MonoBehaviours:
[SerializeField, HideInInspector]
private List<MonoBehaviour> components = new();
```

* **SerializationMode.AllCustomComponents** (default): captures every custom MonoBehaviour on the GameObject.
* **SerializationMode.SelectedComponents**: only snapshots the list you pick via the mask field.

### 5 How the save / load cycle works

* **On save**, `SerializeComponentData()` calls `GetTargets()` → iterates each target component, builds a `ComponentSnapshot` of its fields, then serializes the list via `SaveDataSerializer`.
* **On load**, `DeserializeComponentData(byte[] data)` reconstructs each `ComponentSnapshot`, locates or (`AddComponent`) the target type, then reflects through each saved `FieldSnapshot`, performing a safe conversion and setting the field via `FieldInfo.SetValue`

### 6 Supported Types

* **Primitives**: `int`, `float`, `double`, `bool`, `string`
* **UnityEngine Objects**: `GameObject` (by UniqueID), `Transform`, `Texture2D`, `AudioClip`, `AnimationClip`, `Sprite`, `Material`, etc.
* **Structs**: `Vector2`, `Vector3`, `Color`
* **Collections**: any `IList` → `List<TypedObject>`, any `IDictionary` → `Dictionary<TypedObject, TypedObject>`
* **Enums**
* **GameCreator types** (if present) via conditional compilation wrappers

### 7 Limitations

* **Field-only**
  * Only serializes **fields**—not C# properties or methods.
* **SerializeField/Public Only**
  * Private fields must carry `[SerializeField]`; otherwise they’re ignored
* **Supported Types Only**
  * If a field’s type isn’t in the `TypedObjectFactory` map (e.g. a custom class), it will be skipped with a warning. Complex nested or cyclic references aren’t handled.
* **Unity Object References**
  * `UnityEngine.Object` fields must be assigned in the Inspector; null references are silently skipped
* **Performance**
  * Reflection has overhead—avoid huge collections or per-frame use. Best for occasional save/load cycles.

### 8 Extending the component

To handle extra data per component type:

1. Subclass `RememberCustomComponents`.
2. Override `SerializeComponentData()` / `DeserializeComponentData()`, call `base`, then append or process your extra fields.
3. Register your subclass in the Composite (if using `RememberComposite`) or add it directly.

### 9 Troubleshooting & FAQ

* **Fields aren’t restored** → check they’re public or marked `[SerializeField]`.
* **“Unsupported field type…” warnings** → inspect logs; unsupported types simply aren’t saved. Consider writing a custom `TypedObjectFactory` extension.
* **Component not added on load** → the `ComponentType` string must match an accessible type via `Type.GetType(…)`; custom namespaces/assemblies must be resolvable.

You’re all set—hook your UI or gameplay code to SaveManager’s save/load calls, and RememberCustomComponents will travel with every slot, transparently preserving your custom MonoBehaviour state.
