Saving & Loading
Saving and loading Feel Speak data.
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'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. 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
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.
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);
});
}
}Last updated