# Saving & Loading

Feel Speak doesn't have an internal method for saving data, as it's not a save system. However, saving and loading Feel Speak data is quite simple with external save systems. Any save system that uses JSON or binary serialization should be able to save and load Feel Speak's data.

## Speaker Dialogue

You may already know that you can set a [speaker](https://stylishesper.gitbook.io/feel-speak/scripting/api/overworld/speaker "mention")'s dialogue graph by setting the `dialogue` field. If you're dynamically changing the value, you can save what the current dialogue is by saving the ID or name of the dialogue graph.

## Choices

Each choice has a name field. Names should be unique, as they can be used to identify a choice. The purpose of unique choice names is so that you can check if a specific choice was made by the player by saving the choice when it's made. This can be done with the `onChoiceMade` event.

## Examples

The code below is how you can save and load speaker dialogue and all choices made with [ESave](https://app.gitbook.com/o/vQC9VbiGJfIp0CaKhYvJ/s/korEE1oahhwAkGIn7ek0/ "mention"). ESave is my own save system—it's entirely free, and it's been tested with Feel Speak. ESave is not a requirement; you can use the save system of your choice. However, the examples below will only work with ESave.

### With ESave Free

```csharp
using Esper.ESave;
using Esper.FeelSpeak;
using Esper.FeelSpeak.Graph;
using Esper.FeelSpeak.Graph.Data;
using Esper.FeelSpeak.Overworld;
using UnityEngine;

public class FeelSpeakSavingExample : MonoBehaviour
{
    /// <summary>
    /// The save file.
    /// </summary>
    private SaveFile saveFile;

    /// <summary>
    /// The speaker to save data for.
    /// </summary>
    [SerializeField]
    private Speaker speaker;

    private void Awake()
    {
        // Get the save file from the SaveFileSetup component
        saveFile = GetComponent<SaveFileSetup>().GetSaveFile();

        // Add an event that will save a choice when it's made
        Dialogue.onChoiceMade.AddListener(SaveChoice);
    }

    /// <summary>
    /// Saves a choice.
    /// </summary>
    /// <param name="choice">The choice to save.</param>
    public void SaveChoice(Choice choice)
    {
        // Technically the whole Choice struct can be saved, but we really only need to save the name
        // for checking purposes. The value type we save it as doesn't matter since we only need to
        // to check if the choice was made or not, which we will do with saveFile.HasData("choice name").
        saveFile.AddOrUpdateData(choice.name, true);

        // Confirm changes. This is simply here for informational purposes. Save should actually be
        // called as minimally as possible.
        saveFile.Save();
    }

    /// <summary>
    /// Checks if a choice was made.
    /// </summary>
    /// <param name="name">The name of the choice.</param>
    /// <returns>True if the specific choice was made by the player. Otherwise, false.</returns>
    public bool WasChoiceMade(string name)
    {
        return saveFile.HasData(name);
    }

    /// <summary>
    /// Saves the speaker's current dialogue.
    /// </summary>
    public void SaveSpeakerDialogue()
    {
        // Get the dialogue graph ID
        var dialogueGraphId = speaker.dialogue.id;

        // Save it
        saveFile.AddOrUpdateData("MySpeakerDialogue", dialogueGraphId);

        // Confirm changes
        saveFile.Save();
    }

    /// <summary>
    /// Loads and sets the speaker's current dialogue from the save file.
    /// </summary>
    public void LoadSpeakerDialogue()
    {
        // Loads the dialogue graph ID
        var dialogueGraphId = saveFile.GetData<int>("MySpeakerDialogue");

        // Set it to the speaker by using the ID to get the graph
        speaker.dialogue = FeelSpeak.GetDialogueGraph(dialogueGraphId);
    }
}
```

### ESave Pro

Ensure ESave is initialized before attempting to save and load.

```csharp
using Esper.ESave;
using Esper.FeelSpeak;
using Esper.FeelSpeak.Graph;
using Esper.FeelSpeak.Graph.Data;
using Esper.FeelSpeak.Overworld;
using UnityEngine;

public class FeelSpeakSavingExample : MonoBehaviour
{
    /// <summary>
    /// The save state.
    /// </summary>
    private SaveState saveState;

    /// <summary>
    /// The speaker to save data for.
    /// </summary>
    [SerializeField]
    private Speaker speaker;

    private void Awake()
    {
        // Get the save state
        saveState = ESave.GetSaveState(0);

        // Add an event that will save a choice when it's made
        Dialogue.onChoiceMade.AddListener(SaveChoice);
    }

    /// <summary>
    /// Saves a choice.
    /// </summary>
    /// <param name="choice">The choice to save.</param>
    public void SaveChoice(Choice choice)
    {
        // Technically the whole Choice struct can be saved, but we really only need to save the name
        // for checking purposes. The value type we save it as doesn't matter since we only need to
        // to check if the choice was made or not, which we will do with saveState.HasData("choice name").
        saveState.AddData(choice.name, true);

        // Confirm changes. This is simply here for informational purposes. ESave.Save should actually be
        // called as minimally as possible.
        ESave.Save(saveState);
    }

    /// <summary>
    /// Checks if a choice was made.
    /// </summary>
    /// <param name="name">The name of the choice.</param>
    /// <returns>True if the specific choice was made by the player. Otherwise, false.</returns>
    public bool WasChoiceMade(string name)
    {
        return saveState.HasData(name);
    }

    /// <summary>
    /// Saves the speaker's current dialogue.
    /// </summary>
    public void SaveSpeakerDialogue()
    {
        // Get the dialogue graph ID
        var dialogueGraphId = speaker.dialogue.id;

        // Save it
        saveState.AddData("MySpeakerDialogue", dialogueGraphId).OnComplete(_ =>
        {
            // Confirm changes
            ESave.Save(saveState);
        });
    }

    /// <summary>
    /// Loads and sets the speaker's current dialogue from the save state.
    /// </summary>
    public void LoadSpeakerDialogue()
    {
        // Loads the dialogue graph ID
        saveState.GetData<int>("MySpeakerDialogue").OnComplete(dialogueGraphId =>
        {
            // Set it to the speaker by using the ID to get the graph
            speaker.dialogue = FeelSpeak.GetDialogueGraph(dialogueGraphId);
        });
    }
}
```
