# How to Implement Save and Load Functionality in the Undertale‑Changer Template

> Implement Undertale save and load functionality using Undertale-Changer-Template. Learn to serialize PlayerControl data and FactTables with a JSON-based system for easy game state management.

- Repository: [Archived AIk/undertale-changer-template](https://github.com/arch-aik/undertale-changer-template)
- Tags: how-to-guide
- Published: 2026-02-25

---

**The Undertale‑Changer Template provides a complete JSON‑based save system centered around `SaveController`, `SaveService`, and `SaveBoxController`, allowing you to serialize `PlayerControl` data and FactTables to `Assets/Data/` and restore them later with automatic file management.**

The Undertale‑Changer Template is a Unity-based framework that ships with a production-ready save system. You do not need to build serialization logic from scratch; instead, you interface with three core components that handle JSON conversion, file I/O, and UI flow according to the `arch-aik/undertale-changer-template` source code.

## Understanding the Core Save Architecture

The save system relies on three coordinated components:

- **`SaveController`** ([`Assets/Scripts/UCT/Core/SaveController.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/Assets/Scripts/UCT/Core/SaveController.cs)) – Handles low-level serialization, file writes to the `Assets/Data/` directory, and automatic renaming of save slots.
- **`SaveService`** (defined within [`Assets/Scripts/UCT/Overworld/SaveBoxController.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/Assets/Scripts/UCT/Overworld/SaveBoxController.cs)) – A thin façade that triggers saves and persists player preferences (language, resolution) via `PlayerPrefs`.
- **`SaveBoxController`** ([`Assets/Scripts/UCT/Overworld/SaveBoxController.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/Assets/Scripts/UCT/Overworld/SaveBoxController.cs)) – Manages the save UI dialog, captures confirmation input, and calls `SaveService.SaveGame()`.

## How the Save System Works

### The Saving Process

When the player initiates a save, the following chain executes:

1. **UI Confirmation** – `SaveBoxController.HandleConfirmationInput` detects the **Z** key press and calls `ProcessSaveConfirmation`.
2. **Service Trigger** – `ProcessSaveConfirmation` invokes `SaveService.SaveGame()`, which delegates to `SaveController.SaveData(PlayerControl player, string dataName)`.
3. **JSON Serialization** – `SaveData` ensures the `Assets/Data` folder exists, serializes the `PlayerControl` instance using `JsonConvert.SerializeObject`, and writes it to `{dataName}.json`.
4. **FactTable Persistence** – The same method calls `SaveFactTablesToJson` to capture the current state of all `FactTable` assets in `Resources/Tables`.
5. **Preferences Update** – `SaveService.SaveGame` finishes by calling `SavePlayerPreferences` to cache settings like language and resolution.

### The Loading Process

Loading reverses the flow via `SaveController.LoadData(string dataName)`:

1. **File Management** – `LoadData` first calls `SortAndRenameData` to ensure save files follow a continuous sequence ([`Data0.json`](https://github.com/arch-aik/undertale-changer-template/blob/main/Data0.json), [`Data1.json`](https://github.com/arch-aik/undertale-changer-template/blob/main/Data1.json), etc.).
2. **Instance Creation** – A fresh `PlayerControl` ScriptableObject is created with `ScriptableObject.CreateInstance<PlayerControl>()`.
3. **Deserialization** – `JsonConvert.PopulateObject` reads the JSON file and populates the instance fields (name, level, position).
4. **State Restoration** – The loaded `PlayerControl` is cached in `UsersData`, and `LoadFactTablesFromJson` re‑hydrates the event system state.

### FactTable Persistence

**FactTables** are ScriptableObjects used by the event system (`EventTable`, `RuleTable`). The save system walks the `Resources/Tables` folder, serializes each table’s `facts` list to JSON, and restores it on load, ensuring events continue exactly where they left off.

## Implementing Save Functionality

### Triggering a Save from the UI

Use the built-in save dialog to handle confirmation flow automatically:

```csharp
using UnityEngine;
using UCT.Overworld;

public class MySaveButton : MonoBehaviour
{
    public void OnClick()
    {
        // Opens the built-in save UI and handles confirmation
        SaveBoxController.Instance.OpenSaveBox();
    }
}

```

Calling `SaveBoxController.Instance.OpenSaveBox()` presents the player with the standard save dialog, which eventually reaches `SaveService.SaveGame()` and writes the file.

### Saving Custom Data Automatically

Because `SaveController.SaveData` serializes the entire `PlayerControl` instance, you can extend the save payload by adding fields to the `PlayerControl` ScriptableObject:

```csharp
[Serializable]
public class PlayerControl : ScriptableObject
{
    public List<string> inventory = new List<string>();   // Custom data
    public int level;
    public Vector3 position;
    // Existing fields...
}

```

No additional changes are required; `JsonConvert.SerializeObject` will capture the `inventory` list automatically.

## Implementing Load Functionality

### Loading a Specific Slot Programmatically

To load a specific save slot (e.g., "Data3") from a custom menu:

```csharp
using UnityEngine;
using UCT.Core;

public class MyLoadButton : MonoBehaviour
{
    public void OnClick()
    {
        var player = SaveController.LoadData("Data3");
        if (player != null)
        {
            MainControl.Instance.playerControl = player;
            // Fact tables are restored automatically by LoadData
        }
        else
        {
            Debug.LogWarning("Save slot not found.");
        }
    }
}

```

This restores the `PlayerControl` state and all associated FactTables from [`Assets/Data/Data3.json`](https://github.com/arch-aik/undertale-changer-template/blob/main/Assets/Data/Data3.json).

## Managing Save Files

The template includes utilities for save slot maintenance:

- **`GetDataNumber`** – Counts existing save files.
- **`DeleteData(string dataName)`** – Removes a specific save file.
- **`SortAndRenameData`** – Renames remaining files to maintain a continuous sequence after deletion.

### Deleting a Save Slot

```csharp
using UCT.Core;

public class DeleteSaveSlot : MonoBehaviour
{
    public void RemoveSlot(int slotIndex)
    {
        SaveController.DeleteData($"Data{slotIndex}");
        // Add UI refresh logic here
    }
}

```

After deletion, `SortAndRenameData` ensures the remaining files are renamed to [`Data0.json`](https://github.com/arch-aik/undertale-changer-template/blob/main/Data0.json), [`Data1.json`](https://github.com/arch-aik/undertale-changer-template/blob/main/Data1.json), etc., preventing gaps in the numbering.

## Summary

- The Undertale‑Changer Template implements save/load via **SaveController**, **SaveService**, and **SaveBoxController**.
- Save data is stored as JSON in `Assets/Data/`, with automatic file renaming handled by `SortAndRenameData`.
- **PlayerControl** instances are serialized with `JsonConvert.SerializeObject` and restored with `JsonConvert.PopulateObject`.
- **FactTables** are persisted alongside player data to maintain event system state.
- Player preferences (language, resolution) are cached via `PlayerPrefs` through `SaveService`.

## Frequently Asked Questions

### Where are save files physically stored?

Save files are written to the `Assets/Data/` directory within your Unity project as JSON files (e.g., [`Data0.json`](https://github.com/arch-aik/undertale-changer-template/blob/main/Data0.json), [`Data1.json`](https://github.com/arch-aik/undertale-changer-template/blob/main/Data1.json)). This path is hardcoded in `SaveController.SaveData`, which ensures the directory exists before writing.

### How do I add support for multiple save slots?

The system natively supports multiple slots. Simply pass a unique name (e.g., `"Data0"`, `"Data1"`) to `SaveController.SaveData` or `SaveController.LoadData`. The `SortAndRenameData` utility automatically renumbers files to maintain a continuous sequence when slots are deleted.

### What happens to the event system state when I save?

The event system state is preserved via **FactTables**. `SaveFactTablesToJson` serializes all `FactTable` assets found in `Resources/Tables`, and `LoadFactTablesFromJson` restores them when loading. This ensures story flags and rule states persist across sessions.

### Can I customize what gets saved without modifying the core system?

Yes. Extend the `PlayerControl` ScriptableObject with additional `[Serializable]` fields. Because `SaveController.SaveData` serializes the entire `PlayerControl` instance using `JsonConvert.SerializeObject`, any new fields you add will be automatically included in the JSON output without touching the save logic in [`SaveController.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/SaveController.cs).