Save/Load

Behavior trees and their variables can be saved to a file allowing the the behavior tree to be restored at the same state later on. Individual behavior trees can be saved and loaded by calling BehaviorTree.Save/Load, or you can use the Save Manager if you want to save multiple behavior trees to the same file.

Behavior Tree Save/Load

The script below demonstrates saving and loading a single behavior tree.

using Opsive.BehaviorDesigner.Runtime;
using Opsive.BehaviorDesigner.Runtime.Utility;
using UnityEngine;

public class Saver : MonoBehaviour
{
    [Tooltip("The behavior tree that should be saved.")]
    public BehaviorTree m_BehaviorTree;
    [Tooltip("The location that the behavior tree should be saved.")]
    public string m_SaveLocation = "Assets/BehaviorTree.save";

    /// <summary>
    /// Saves the behavior tree.
    /// </summary>
    public void Save()
    {
        m_BehaviorTree.Save(m_SaveLocation, SaveManager.VariableSaveScope.GameObjectVariables | SaveManager.VariableSaveScope.SceneVariables); // Saves the behavior tree and the GameObject/scene variables.
    }

    /// <summary>
    /// Restores the behavior tree.
    /// </summary>
    public void Load()
    {
        m_BehaviorTree.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 behavior tree 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.BehaviorDesigner.Runtime;
using Opsive.BehaviorDesigner.Runtime.Utility;
using UnityEngine;

public class Saver : MonoBehaviour
{
    [Tooltip("The behavior trees that should be saved.")]
    public BehaviorTree[] m_BehaviorTrees;
    [Tooltip("The location that the behavior trees should be saved.")]
    public string m_SaveLocation = "Assets/BehaviorTrees.save";

    /// <summary>
    /// Saves the behavior tree.
    /// </summary>
    public void Save()
    {
        SaveManager.Save(m_BehaviorTrees, m_SaveLocation, SaveManager.VariableSaveScope.GameObjectVariables | SaveManager.VariableSaveScope.SceneVariables); // Saves the behavior tree and the GameObject/scene variables.
    }

    /// <summary>
    /// Restores the behavior tree.
    /// </summary>
    public void Load()
    {
        SaveManager.Load(m_BehaviorTrees, m_SaveLocation);
    }
}
Save Data

In the previous examples the behavior tree 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 behavior tree data is saved along with other agent data.

See the SaveLoad sample scene for a working example of the save load system.
    
    /// <summary>
    /// Stores all of the agent save data in one structure.
    /// </summary>
    private struct AgentSaveData
    {
        public SaveData BehaviorTreeSaveData; // 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_BehaviorTree.Save();
        if (!saveData.HasValue) {
            return;
        }

        // Create the data structure which contains all of the values that should be saved.
        var agentSaveData = new AgentSaveData() { BehaviorTreeSaveData = 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_BehaviorTree.Load(agentSaveData.BehaviorTreeSaveData);

        m_Transform.SetPositionAndRotation(agentSaveData.Position, agentSaveData.Rotation);
    }