Save/Load
State machines and their variables can be saved to a file allowing the the state machine to be restored at the same state later on. Individual state machines can be saved and loaded by calling StateMachine.Save/Load, or you can use the Save Manager if you want to save multiple state machines to the same file.
State Machine Save/Load
The script below demonstrates saving and loading a single state machine.
using Opsive.StateDesigner.Runtime;
using Opsive.StateDesigner.Runtime.Utility;
using UnityEngine;
public class Saver : MonoBehaviour
{
[Tooltip("The state machine that should be saved.")]
public StateMachine m_StateMachine;
[Tooltip("The location that the state machine should be saved.")]
public string m_SaveLocation = "Assets/StateMachine.save";
/// <summary>
/// Saves the state machine.
/// </summary>
public void Save()
{
m_StateMachine.Save(m_SaveLocation, SaveManager.VariableSaveScope.GameObjectVariables | SaveManager.VariableSaveScope.SceneVariables); // Saves the state machine and the GameObject/scene variables.
}
/// <summary>
/// Restores the state machine.
/// </summary>
public void Load()
{
m_StateMachine.Load(m_SaveLocation);
}
}
The second parameter is a flag specifying what additional variables should be saved. The graph variable values will always be saved when the state machine is saved.
Save Manager Save/Load
Multiple behavior trees can be saved to the same file using the Save Manager. The script below has the same functionality as Behavior Tree save script except it uses a behavior tree array.
using Opsive.StateDesigner.Runtime;
using Opsive.StateDesigner.Runtime.Utility;
using UnityEngine;
public class Saver : MonoBehaviour
{
[Tooltip("The state machines that should be saved.")]
public StateMachine [] m_StateMachines;
[Tooltip("The location that the state machines should be saved.")]
public string m_SaveLocation = "Assets/StateMachine.save";
/// <summary>
/// Saves the state machine.
/// </summary>
public void Save()
{
SaveManager.Save(m_StateMachines, m_SaveLocation, SaveManager.VariableSaveScope.GameObjectVariables | SaveManager.VariableSaveScope.SceneVariables); // Saves the state machine and the GameObject/scene variables.
}
/// <summary>
/// Restores the state machine.
/// </summary>
public void Load()
{
SaveManager.Load(m_StateMachines, m_SaveLocation);
}
}
Save Data
In the previous examples the state machine is saved and loaded from a file path. The raw save data can also be retrieved allowing you to use other methods in order to save the data. In the example below the state machine data is saved along with other data.
/// <summary>
/// Stores all of the agent save data in one structure.
/// </summary>
private struct AgentSaveData
{
public SaveData StateMachineSaveData; // The behavior tree save data.
public Vector3 Position; // The Transform position.
public Quaternion Rotation; // The Transform rotation.
}
/// <summary>
/// Save the agent state.
/// </summary>
public void Save()
{
var saveData = m_StateMachine.Save();
if (!saveData.HasValue) {
return;
}
// Create the data structure which contains all of the values that should be saved.
var agentSaveData = new AgentSaveData() { StateMachineSaveData = saveData.Value, Position = m_Transform.position, Rotation = m_Transform.rotation };
if (File.Exists(m_SaveLocation)) {
File.Delete(m_SaveLocation);
}
try {
if (!Directory.Exists(Path.GetDirectoryName(m_SaveLocation))) {
Directory.CreateDirectory(Path.GetDirectoryName(m_SaveLocation));
}
var fileStream = File.Create(m_SaveLocation);
using (var streamWriter = new StreamWriter(fileStream)) {
streamWriter.Write(JsonUtility.ToJson(agentSaveData));
}
fileStream.Close();
} catch (System.Exception e) {
Debug.LogException(e);
return;
}
}
/// <summary>
/// Load the agent state.
/// </summary>
public void Load()
{
if (!File.Exists(m_SaveLocation)) {
return;
}
AgentSaveData agentSaveData;
var fileStream = File.Open(m_SaveLocation, FileMode.Open);
using (var streamReader = new StreamReader(fileStream)) {
var fileData = streamReader.ReadToEnd();
agentSaveData = JsonUtility.FromJson<AgentSaveData>(fileData);
}
fileStream.Close();
// Restore the values.
m_StateMachine.Load(agentSaveData.StateMachineSaveData);
m_Transform.SetPositionAndRotation(agentSaveData.Position, agentSaveData.Rotation);
}