Browse Source

Merge pull request #586 from snozbot/save-system

Added save system and SaveGame example scene + documentation
master
Chris Gregan 8 years ago committed by GitHub
parent
commit
b44149a28b
  1. 54
      Assets/Fungus/Resources/Prefabs/SaveData.prefab
  2. 8
      Assets/Fungus/Resources/Prefabs/SaveData.prefab.meta
  3. 2233
      Assets/Fungus/Resources/Prefabs/SaveMenu.prefab
  4. 8
      Assets/Fungus/Resources/Prefabs/SaveMenu.prefab.meta
  5. 18
      Assets/Fungus/Scripts/Commands/Call.cs
  6. 2
      Assets/Fungus/Scripts/Commands/DeleteSaveKey.cs
  7. 2
      Assets/Fungus/Scripts/Commands/LoadVariable.cs
  8. 4
      Assets/Fungus/Scripts/Commands/Menu.cs
  9. 156
      Assets/Fungus/Scripts/Commands/SavePoint.cs
  10. 12
      Assets/Fungus/Scripts/Commands/SavePoint.cs.meta
  11. 2
      Assets/Fungus/Scripts/Commands/SaveVariable.cs
  12. 10
      Assets/Fungus/Scripts/Commands/SetSaveProfile.cs
  13. 23
      Assets/Fungus/Scripts/Components/Block.cs
  14. 1
      Assets/Fungus/Scripts/Components/Flowchart.cs
  15. 18
      Assets/Fungus/Scripts/Components/FungusManager.cs
  16. 72
      Assets/Fungus/Scripts/Components/SaveData.cs
  17. 12
      Assets/Fungus/Scripts/Components/SaveData.cs.meta
  18. 277
      Assets/Fungus/Scripts/Components/SaveManager.cs
  19. 12
      Assets/Fungus/Scripts/Components/SaveManager.cs.meta
  20. 294
      Assets/Fungus/Scripts/Components/SaveMenu.cs
  21. 12
      Assets/Fungus/Scripts/Components/SaveMenu.cs.meta
  22. 14
      Assets/Fungus/Scripts/Components/SayDialog.cs
  23. 4
      Assets/Fungus/Scripts/Editor/CallEditor.cs
  24. 54
      Assets/Fungus/Scripts/Editor/EventHandlerEditor.cs
  25. 6
      Assets/Fungus/Scripts/Editor/MenuEditor.cs
  26. 34
      Assets/Fungus/Scripts/Editor/SaveDataEditor.cs
  27. 12
      Assets/Fungus/Scripts/Editor/SaveDataEditor.cs.meta
  28. 22
      Assets/Fungus/Scripts/Editor/SaveMenuItems.cs
  29. 8
      Assets/Fungus/Scripts/Editor/SaveMenuItems.cs.meta
  30. 2
      Assets/Fungus/Scripts/EventHandlers/FlowchartEnabled.cs
  31. 2
      Assets/Fungus/Scripts/EventHandlers/MessageReceived.cs
  32. 45
      Assets/Fungus/Scripts/EventHandlers/SavePointLoaded.cs
  33. 12
      Assets/Fungus/Scripts/EventHandlers/SavePointLoaded.cs.meta
  34. 30
      Assets/Fungus/Scripts/Signals/SaveManagerSignals.cs
  35. 12
      Assets/Fungus/Scripts/Signals/SaveManagerSignals.cs.meta
  36. 216
      Assets/Fungus/Scripts/Utils/FlowchartData.cs
  37. 12
      Assets/Fungus/Scripts/Utils/FlowchartData.cs.meta
  38. 11
      Assets/Fungus/Scripts/Utils/FungusConstants.cs
  39. 45
      Assets/Fungus/Scripts/Utils/SaveDataItem.cs
  40. 12
      Assets/Fungus/Scripts/Utils/SaveDataItem.cs.meta
  41. 132
      Assets/Fungus/Scripts/Utils/SaveHistory.cs
  42. 12
      Assets/Fungus/Scripts/Utils/SaveHistory.cs.meta
  43. 117
      Assets/Fungus/Scripts/Utils/SavePointData.cs
  44. 12
      Assets/Fungus/Scripts/Utils/SavePointData.cs.meta
  45. BIN
      Assets/Fungus/Textures/GreyButton.png
  46. 84
      Assets/Fungus/Textures/GreyButton.png.meta
  47. BIN
      Assets/Fungus/Textures/rewind.png
  48. 84
      Assets/Fungus/Textures/rewind.png.meta
  49. BIN
      Assets/Fungus/Textures/settings.png
  50. 59
      Assets/Fungus/Textures/settings.png.meta
  51. 9
      Assets/FungusExamples/SaveGame.meta
  52. 4625
      Assets/FungusExamples/SaveGame/SaveGame.unity
  53. 8
      Assets/FungusExamples/SaveGame/SaveGame.unity.meta
  54. 351
      Assets/Tests/Flow/FlowTests.unity
  55. 2337
      Assets/Tests/Narrative/NarrativeTests.unity
  56. 9
      Assets/Tests/Save.meta
  57. 501
      Assets/Tests/Save/LoadFlowchart.unity
  58. 8
      Assets/Tests/Save/LoadFlowchart.unity.meta
  59. 554
      Assets/Tests/Save/SaveFlowchart.unity
  60. 8
      Assets/Tests/Save/SaveFlowchart.unity.meta
  61. 1
      Docs/Docs.mdproj
  62. 2
      Docs/Doxyfile
  63. 13
      Docs/command_ref/core_events.md
  64. 16
      Docs/command_ref/flow_commands.md
  65. 25
      Docs/command_ref/scene_events.md
  66. 1
      Docs/command_ref/sprite_events.md
  67. 134
      Docs/fungus_docs/save_system.md
  68. BIN
      Docs/resources/save_system/save_history.png
  69. BIN
      Docs/resources/save_system/save_menu.png
  70. 1
      Docs/top_pages/mainpage.md
  71. 4
      ProjectSettings/EditorBuildSettings.asset
  72. 3
      ProjectSettings/ProjectSettings.asset

54
Assets/Fungus/Resources/Prefabs/SaveData.prefab

@ -0,0 +1,54 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1001 &100100000
Prefab:
m_ObjectHideFlags: 1
serializedVersion: 2
m_Modification:
m_TransformParent: {fileID: 0}
m_Modifications: []
m_RemovedComponents: []
m_ParentPrefab: {fileID: 0}
m_RootGameObject: {fileID: 1310974650352510}
m_IsPrefabParent: 1
--- !u!1 &1310974650352510
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
serializedVersion: 5
m_Component:
- component: {fileID: 4704521519618994}
- component: {fileID: 114272980009688704}
m_Layer: 0
m_Name: SaveData
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &4704521519618994
Transform:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1310974650352510}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 1079.5829, y: 593.8655, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &114272980009688704
MonoBehaviour:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1310974650352510}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 60d92858185944732937980806717234, type: 3}
m_Name:
m_EditorClassIdentifier:
flowcharts: []

8
Assets/Fungus/Resources/Prefabs/SaveData.prefab.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: eae76c041b933476bbe9bdd4c3d80793
timeCreated: 1483972230
licenseType: Free
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:

2233
Assets/Fungus/Resources/Prefabs/SaveMenu.prefab

File diff suppressed because it is too large Load Diff

8
Assets/Fungus/Resources/Prefabs/SaveMenu.prefab.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: bd2b99773f3e0489aae9f9b5053ad360
timeCreated: 1481298777
licenseType: Free
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:

18
Assets/Fungus/Scripts/Commands/Call.cs

@ -37,6 +37,9 @@ namespace Fungus
[Tooltip("Block to start executing")]
[SerializeField] protected Block targetBlock;
[Tooltip("Label to start exeuction at. Takes priority over startIndex.")]
[SerializeField] protected StringData startLabel = new StringData();
[Tooltip("Command index to start executing")]
[FormerlySerializedAs("commandIndex")]
[SerializeField] protected int startIndex;
@ -70,6 +73,17 @@ namespace Fungus
};
}
// Find the command index to start execution at
int index = startIndex;
if (startLabel != "")
{
int labelIndex = targetBlock.GetLabelIndex(startLabel);
if (labelIndex != -1)
{
index = labelIndex;
}
}
if (targetFlowchart == null ||
targetFlowchart.Equals(GetFlowchart()))
{
@ -80,12 +94,12 @@ namespace Fungus
flowchart.SelectedBlock = targetBlock;
}
StartCoroutine(targetBlock.Execute(startIndex, onComplete));
StartCoroutine(targetBlock.Execute(index, onComplete));
}
else
{
// Execute block in another Flowchart
targetFlowchart.ExecuteBlock(targetBlock, startIndex, onComplete);
targetFlowchart.ExecuteBlock(targetBlock, index, onComplete);
}
}

2
Assets/Fungus/Scripts/Commands/DeleteSaveKey.cs

@ -30,7 +30,7 @@ namespace Fungus
var flowchart = GetFlowchart();
// Prepend the current save profile (if any)
string prefsKey = SetSaveProfile.saveProfile + "_" + flowchart.SubstituteVariables(key);
string prefsKey = SetSaveProfile.SaveProfile + "_" + flowchart.SubstituteVariables(key);
PlayerPrefs.DeleteKey(prefsKey);

2
Assets/Fungus/Scripts/Commands/LoadVariable.cs

@ -38,7 +38,7 @@ namespace Fungus
var flowchart = GetFlowchart();
// Prepend the current save profile (if any)
string prefsKey = SetSaveProfile.saveProfile + "_" + flowchart.SubstituteVariables(key);
string prefsKey = SetSaveProfile.SaveProfile + "_" + flowchart.SubstituteVariables(key);
System.Type variableType = variable.GetType();

4
Assets/Fungus/Scripts/Commands/Menu.cs

@ -35,7 +35,9 @@ namespace Fungus
[Tooltip("A custom Menu Dialog to use to display this menu. All subsequent Menu commands will use this dialog.")]
[SerializeField] protected MenuDialog setMenuDialog;
#region Public member
#region Public members
public MenuDialog SetMenuDialog { get { return setMenuDialog; } set { setMenuDialog = value; } }
public override void OnEnter()
{

156
Assets/Fungus/Scripts/Commands/SavePoint.cs

@ -0,0 +1,156 @@
// This code is part of the Fungus library (http://fungusgames.com) maintained by Chris Gregan (http://twitter.com/gofungus).
// It is released for free under the MIT open source license (https://github.com/snozbot/fungus/blob/master/LICENSE)
#if UNITY_5_3_OR_NEWER
using UnityEngine;
namespace Fungus
{
[CommandInfo("Flow",
"Save Point",
"Creates a Save Point and adds it to the Save History. The player can save the Save History to persistent storage and load it again later using the Save Menu.")]
public class SavePoint : Command
{
/// <summary>
/// Supported modes for specifying a Save Point Key.
/// </summary>
public enum KeyMode
{
/// <summary> Use the parent Block's name as the Save Point Key. N.B. If you change the Block name later it will break the save file!</summary>
UseBlockName,
/// <summary> Use a custom string for the key. This allows you to use multiple Save Points in the same block and save files will still work if the Block is renamed later. </summary>
Custom
}
/// <summary>
/// Supported modes for specifying a Save Point Description.
/// </summary>
public enum DescriptionMode
{
/// <summary> Uses the current date and time as the save point description.</summary>
Timestamp,
/// <summary> Use a custom string for the save point description.</summary>
Custom
}
[Tooltip("Marks this Save Point as the starting point for Flowchart execution in the scene. Each scene in your game should have exactly one Save Point with this enabled.")]
[SerializeField] protected bool isStartPoint = false;
[Tooltip("How the Save Point Key for this Save Point is defined.")]
[SerializeField] protected KeyMode keyMode = KeyMode.UseBlockName;
[Tooltip("A string key which uniquely identifies this save point.")]
[SerializeField] protected string customKey = "";
[Tooltip("How the description for this Save Point is defined.")]
[SerializeField] protected DescriptionMode descriptionMode = DescriptionMode.Timestamp;
[Tooltip("A short description of this save point.")]
[SerializeField] protected string customDescription;
[Tooltip("Fire a Save Point Loaded event when this command executes.")]
[SerializeField] protected bool fireEvent = true;
[Tooltip("Resume execution from this location after loading this Save Point.")]
[SerializeField] protected bool resumeOnLoad = true;
#region Public members
/// <summary>
/// Marks this Save Point as the starting point for Flowchart execution in the scene. Each scene in your game should have exactly one Save Point with this enabled.
/// </summary>
public bool IsStartPoint { get { return isStartPoint; } set { isStartPoint = value; } }
/// <summary>
/// Gets a string key which uniquely identifies this Save Point.
/// </summary>
public string SavePointKey
{
get
{
if (keyMode == KeyMode.UseBlockName)
{
return ParentBlock.BlockName;
}
else
{
return customKey;
}
}
}
/// <summary>
/// Gets the save point description.
/// </summary>
public string SavePointDescription
{
get
{
if (descriptionMode == DescriptionMode.Timestamp)
{
return System.DateTime.UtcNow.ToString("HH:mm dd MMMM, yyyy");
}
else
{
return customDescription;
}
}
}
/// <summary>
/// Resume execution from this location after loading this Save Point.
/// </summary>
public bool ResumeOnLoad { get { return resumeOnLoad; } }
public override void OnEnter()
{
var saveManager = FungusManager.Instance.SaveManager;
saveManager.AddSavePoint(SavePointKey, SavePointDescription);
if (fireEvent)
{
SavePointLoaded.NotifyEventHandlers(SavePointKey);
}
Continue();
}
public override string GetSummary()
{
if (keyMode == KeyMode.UseBlockName)
{
return "key: <Block Name>";
}
return "key: " + customKey;
}
public override Color GetButtonColor()
{
return new Color32(235, 191, 217, 255);
}
public override bool IsPropertyVisible(string propertyName)
{
if (propertyName == "customKey" &&
keyMode != KeyMode.Custom)
{
return false;
}
if (propertyName == "customDescription" &&
descriptionMode != DescriptionMode.Custom)
{
return false;
}
return true;
}
#endregion
}
}
#endif

12
Assets/Fungus/Scripts/Commands/SavePoint.cs.meta

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 0b115619cb83b4d6ab8047d0e9407403
timeCreated: 1478530280
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

2
Assets/Fungus/Scripts/Commands/SaveVariable.cs

@ -42,7 +42,7 @@ namespace Fungus
var flowchart = GetFlowchart();
// Prepend the current save profile (if any)
string prefsKey = SetSaveProfile.saveProfile + "_" + flowchart.SubstituteVariables(key);
string prefsKey = SetSaveProfile.SaveProfile + "_" + flowchart.SubstituteVariables(key);
System.Type variableType = variable.GetType();

10
Assets/Fungus/Scripts/Commands/SetSaveProfile.cs

@ -19,12 +19,14 @@ namespace Fungus
[Tooltip("Name of save profile to make active.")]
[SerializeField] protected string saveProfileName = "";
/// <summary>
/// Shared save profile name used by SaveVariable and LoadVariable.
/// </summary>
private static string saveProfile = "";
#region Public members
/// <summary>
/// Shared save profile name used by SaveVariable and LoadVariable.
/// </summary>
public static string saveProfile = "";
public static String SaveProfile { get { return saveProfile; } }
public override void OnEnter()
{

23
Assets/Fungus/Scripts/Components/Block.cs

@ -382,6 +382,29 @@ namespace Fungus
}
}
/// <summary>
/// Returns the index of the Label command with matching key, or -1 if not found.
/// </summary>
public virtual int GetLabelIndex(string labelKey)
{
if (labelKey.Length == 0)
{
return -1;
}
for (int i = 0; i < commandList.Count; i++)
{
var command = commandList[i];
var labelCommand = command as Label;
if (labelCommand != null && String.Compare(labelCommand.Key, labelKey, true) == 0)
{
return i;
}
}
return -1;
}
#endregion
}
}

1
Assets/Fungus/Scripts/Components/Flowchart.cs

@ -3,7 +3,6 @@
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Serialization;
using System;
using System.Text;
using System.Linq;

18
Assets/Fungus/Scripts/Components/FungusManager.cs

@ -1,4 +1,7 @@
using UnityEngine;
// This code is part of the Fungus library (http://fungusgames.com) maintained by Chris Gregan (http://twitter.com/gofungus).
// It is released for free under the MIT open source license (https://github.com/snozbot/fungus/blob/master/LICENSE)
using UnityEngine;
using System.Collections;
namespace Fungus
@ -8,6 +11,9 @@ namespace Fungus
/// </summary>
[RequireComponent(typeof(CameraManager))]
[RequireComponent(typeof(MusicManager))]
#if UNITY_5_3_OR_NEWER
[RequireComponent(typeof(SaveManager))]
#endif
public sealed class FungusManager : MonoBehaviour
{
static FungusManager instance;
@ -18,6 +24,9 @@ namespace Fungus
{
CameraManager = GetComponent<CameraManager>();
MusicManager = GetComponent<MusicManager>();
#if UNITY_5_3_OR_NEWER
SaveManager = GetComponent<SaveManager>();
#endif
}
/// <summary>
@ -45,6 +54,13 @@ namespace Fungus
/// </summary>
public MusicManager MusicManager { get; private set; }
#if UNITY_5_3_OR_NEWER
/// <summary>
/// Gets the save manager singleton instance.
/// </summary>
public SaveManager SaveManager { get; private set; }
#endif
/// <summary>
/// Gets the FungusManager singleton instance.
/// </summary>

72
Assets/Fungus/Scripts/Components/SaveData.cs

@ -0,0 +1,72 @@
// This code is part of the Fungus library (http://fungusgames.com) maintained by Chris Gregan (http://twitter.com/gofungus).
// It is released for free under the MIT open source license (https://github.com/snozbot/fungus/blob/master/LICENSE)
#if UNITY_5_3_OR_NEWER
using UnityEngine;
using System.Collections.Generic;
namespace Fungus
{
/// <summary>
/// This component encodes and decodes a list of game objects to be saved for each Save Point.
/// It knows how to encode / decode concrete game classes like Flowchart and FlowchartData.
/// To extend the save system to handle other data types, just modify or subclass this component.
/// </summary>
public class SaveData : MonoBehaviour
{
protected const string FlowchartDataKey = "FlowchartData";
[Tooltip("A list of Flowchart objects whose variables will be encoded in the save data. Boolean, Integer, Float and String variables are supported.")]
[SerializeField] protected List<Flowchart> flowcharts = new List<Flowchart>();
#region Public methods
/// <summary>
/// Encodes the objects to be saved as a list of SaveDataItems.
/// </summary
public virtual void Encode(List<SaveDataItem> saveDataItems)
{
for (int i = 0; i < flowcharts.Count; i++)
{
var flowchart = flowcharts[i];
var flowchartData = FlowchartData.Encode(flowchart);
var saveDataItem = SaveDataItem.Create(FlowchartDataKey, JsonUtility.ToJson(flowchartData));
saveDataItems.Add(saveDataItem);
}
}
/// <summary>
/// Decodes the loaded list of SaveDataItems to restore the saved game state.
/// </summary>
public virtual void Decode(List<SaveDataItem> saveDataItems)
{
for (int i = 0; i < saveDataItems.Count; i++)
{
var saveDataItem = saveDataItems[i];
if (saveDataItem == null)
{
continue;
}
if (saveDataItem.DataType == FlowchartDataKey)
{
var flowchartData = JsonUtility.FromJson<FlowchartData>(saveDataItem.Data);
if (flowchartData == null)
{
Debug.LogError("Failed to decode Flowchart save data item");
return;
}
FlowchartData.Decode(flowchartData);
}
}
}
#endregion
}
}
#endif

12
Assets/Fungus/Scripts/Components/SaveData.cs.meta

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 60d92858185944732937980806717234
timeCreated: 1483972111
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

277
Assets/Fungus/Scripts/Components/SaveManager.cs

@ -0,0 +1,277 @@
// This code is part of the Fungus library (http://fungusgames.com) maintained by Chris Gregan (http://twitter.com/gofungus).
// It is released for free under the MIT open source license (https://github.com/snozbot/fungus/blob/master/LICENSE)
#if UNITY_5_3_OR_NEWER
using UnityEngine.SceneManagement;
using UnityEngine;
namespace Fungus
{
/// <summary>
/// Manages the Save History (a list of Save Points) and provides a set of operations for saving and loading games.
/// </summary>
public class SaveManager : MonoBehaviour
{
protected static SaveHistory saveHistory = new SaveHistory();
protected virtual bool ReadSaveHistory(string saveDataKey)
{
var historyData = PlayerPrefs.GetString(saveDataKey);
if (!string.IsNullOrEmpty(historyData))
{
var tempSaveHistory = JsonUtility.FromJson<SaveHistory>(historyData);
if (tempSaveHistory != null)
{
saveHistory = tempSaveHistory;
return true;
}
}
return false;
}
protected virtual bool WriteSaveHistory(string saveDataKey)
{
var historyData = JsonUtility.ToJson(saveHistory, true);
if (!string.IsNullOrEmpty(historyData))
{
PlayerPrefs.SetString(saveDataKey, historyData);
PlayerPrefs.Save();
return true;
}
return false;
}
/// <summary>
/// Starts Block execution based on a Save Point Key
/// The execution order is:
/// 1. Save Point Loaded event handlers with a matching key.
/// 2. First Save Point command (in any Block) with matching key. Execution starts at the following command.
/// 3. Any label in any block with name matching the key. Execution starts at the following command.
/// </summary>
protected virtual void ExecuteBlocks(string savePointKey)
{
// Execute Save Point Loaded event handlers with matching key.
SavePointLoaded.NotifyEventHandlers(savePointKey);
// Execute any block containing a SavePoint command matching the save key, with Resume On Load enabled
var savePoints = Object.FindObjectsOfType<SavePoint>();
for (int i = 0; i < savePoints.Length; i++)
{
var savePoint = savePoints[i];
if (savePoint.ResumeOnLoad &&
string.Compare(savePoint.SavePointKey, savePointKey, true) == 0)
{
int index = savePoint.CommandIndex;
var block = savePoint.ParentBlock;
var flowchart = savePoint.GetFlowchart();
flowchart.ExecuteBlock(block, index + 1);
// Assume there's only one SavePoint using this key
break;
}
}
}
/// <summary>
/// Starts execution at the first Save Point found in the scene with the IsStartPoint property enabled.
/// </summary>
protected virtual void ExecuteStartBlock()
{
// Each scene should have one Save Point with the IsStartPoint property enabled.
// We automatically start execution from this command whenever the scene starts 'normally' (i.e. first play, restart or scene load via the Load Scene command or SceneManager.LoadScene).
var savePoints = Object.FindObjectsOfType<SavePoint>();
for (int i = 0; i < savePoints.Length; i++)
{
var savePoint = savePoints[i];
if (savePoint.IsStartPoint)
{
savePoint.GetFlowchart().ExecuteBlock(savePoint.ParentBlock, savePoint.CommandIndex);
break;
}
}
}
protected virtual void LoadSavedGame(string saveDataKey)
{
if (ReadSaveHistory(saveDataKey))
{
saveHistory.ClearRewoundSavePoints();
saveHistory.LoadLatestSavePoint();
}
}
// Scene loading in Unity is asynchronous so we need to take care to avoid race conditions.
// The following callbacks tell us when a scene has been loaded and when
// a saved game has been loaded. We delay taking action until the next
// frame (via a delegate) so that we know for sure which case we're dealing with.
protected virtual void OnEnable()
{
SaveManagerSignals.OnSavePointLoaded += OnSavePointLoaded;
SceneManager.sceneLoaded += OnSceneLoaded;
}
protected virtual void OnDisable()
{
SaveManagerSignals.OnSavePointLoaded -= OnSavePointLoaded;
SceneManager.sceneLoaded -= OnSceneLoaded;
}
protected virtual void OnSavePointLoaded(string savePointKey)
{
var key = savePointKey;
loadAction = () => ExecuteBlocks(key);
}
protected virtual void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
// Ignore additive scene loads
if (mode == LoadSceneMode.Additive)
{
return;
}
// We first assume that this is a 'normal' scene load rather than a saved game being loaded.
// If we subsequently receive a notification that a saved game was loaded then the load action
// set here will be overridden by the OnSavePointLoaded callback above.
if (loadAction == null)
{
loadAction = ExecuteStartBlock;
}
}
protected System.Action loadAction;
protected virtual void Update()
{
// Execute any previously scheduled load action
if (loadAction != null)
{
loadAction();
loadAction = null;
}
}
#region Public members
/// <summary>
/// The default key used for storing save game data in PlayerPrefs.
/// </summary>
public const string DefaultSaveDataKey = "save_data";
/// <summary>
/// The scene that should be loaded when restarting a game.
/// </summary>
public string StartScene { get; set; }
/// <summary>
/// Returns the number of Save Points in the Save History.
/// </summary>
public virtual int NumSavePoints { get { return saveHistory.NumSavePoints; } }
/// <summary>
/// Returns the current number of rewound Save Points in the Save History.
/// </summary>
public virtual int NumRewoundSavePoints { get { return saveHistory.NumRewoundSavePoints; } }
/// <summary>
/// Writes the Save History to persistent storage.
/// </summary>
public virtual void Save(string saveDataKey = DefaultSaveDataKey)
{
WriteSaveHistory(saveDataKey);
}
/// <summary>
/// Loads the Save History from persistent storage and loads the latest Save Point.
/// </summary>
public void Load(string saveDataKey = DefaultSaveDataKey)
{
// Set a load action to be executed on next update
var key = saveDataKey;
loadAction = () => LoadSavedGame(key);
}
/// <summary>
/// Deletes a previously stored Save History from persistent storage.
/// </summary>
public void Delete(string saveDataKey = DefaultSaveDataKey)
{
PlayerPrefs.DeleteKey(saveDataKey);
PlayerPrefs.Save();
}
/// <summary>
/// Returns true if save data has previously been stored using this key.
/// </summary>
public bool SaveDataExists(string saveDataKey = DefaultSaveDataKey)
{
return PlayerPrefs.HasKey(saveDataKey);
}
/// <summary>
/// Creates a new Save Point using a key and description, and adds it to the Save History.
/// </summary>
public virtual void AddSavePoint(string savePointKey, string savePointDescription)
{
saveHistory.AddSavePoint(savePointKey, savePointDescription);
SaveManagerSignals.DoSavePointAdded(savePointKey, savePointDescription);
}
/// <summary>
/// Rewinds to the previous Save Point in the Save History and loads that Save Point.
/// </summary>
public virtual void Rewind()
{
if (saveHistory.NumSavePoints > 0)
{
// Rewinding the first save point is not permitted
if (saveHistory.NumSavePoints > 1)
{
saveHistory.Rewind();
}
saveHistory.LoadLatestSavePoint();
}
}
/// <summary>
/// Fast forwards to the next rewound Save Point in the Save History and loads that Save Point.
/// </summary>
public virtual void FastForward()
{
if (saveHistory.NumRewoundSavePoints > 0)
{
saveHistory.FastForward();
saveHistory.LoadLatestSavePoint();
}
}
/// <summary>
/// Deletes all Save Points in the Save History.
/// </summary>
public virtual void ClearHistory()
{
saveHistory.Clear();
}
/// <summary>
/// Returns an info string to help debug issues with the save data.
/// </summary>
/// <returns>The debug info.</returns>
public virtual string GetDebugInfo()
{
return saveHistory.GetDebugInfo();
}
#endregion
}
}
#endif

12
Assets/Fungus/Scripts/Components/SaveManager.cs.meta

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 7cbb6770b607545c4909850d54df3979
timeCreated: 1478861365
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

294
Assets/Fungus/Scripts/Components/SaveMenu.cs

@ -0,0 +1,294 @@
// This code is part of the Fungus library (http://fungusgames.com) maintained by Chris Gregan (http://twitter.com/gofungus).
// It is released for free under the MIT open source license (https://github.com/snozbot/fungus/blob/master/LICENSE)
#if UNITY_5_3_OR_NEWER
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
namespace Fungus
{
/// <summary>
/// A singleton game object which displays a simple UI for the save system.
/// </summary>
public class SaveMenu : MonoBehaviour
{
[Tooltip("Automatically load the most recently saved game on startup")]
[SerializeField] protected bool loadOnStart = true;
[Tooltip("Automatically save game to disk after each Save Point command executes. This also disables the Save and Load menu buttons.")]
[SerializeField] protected bool autoSave = false;
[Tooltip("Delete the save game data from disk when player restarts the game. Useful for testing, but best switched off for release builds.")]
[SerializeField] protected bool restartDeletesSave = false;
[Tooltip("The CanvasGroup containing the save menu buttons")]
[SerializeField] protected CanvasGroup saveMenuGroup;
[Tooltip("The button which hides / displays the save menu")]
[SerializeField] protected Button saveMenuButton;
[Tooltip("The button which saves the save history to disk")]
[SerializeField] protected Button saveButton;
[Tooltip("The button which loads the save history from disk")]
[SerializeField] protected Button loadButton;
[Tooltip("The button which rewinds the save history to the previous save point.")]
[SerializeField] protected Button rewindButton;
[Tooltip("The button which fast forwards the save history to the next save point.")]
[SerializeField] protected Button forwardButton;
[Tooltip("The button which restarts the game.")]
[SerializeField] protected Button restartButton;
[Tooltip("A scrollable text field used for debugging the save data. The text field should be disabled in normal use.")]
[SerializeField] protected ScrollRect debugView;
protected static bool saveMenuActive = false;
protected AudioSource clickAudioSource;
protected LTDescr fadeTween;
protected static SaveMenu instance;
protected virtual void Awake()
{
// Only one instance of SaveMenu may exist
if (instance != null)
{
Destroy(gameObject);
return;
}
instance = this;
GameObject.DontDestroyOnLoad(this);
clickAudioSource = GetComponent<AudioSource>();
}
protected virtual void Start()
{
if (!saveMenuActive)
{
saveMenuGroup.alpha = 0f;
}
var saveManager = FungusManager.Instance.SaveManager;
// Make a note of the current scene. This will be used when restarting the game.
if (string.IsNullOrEmpty(saveManager.StartScene))
{
saveManager.StartScene = SceneManager.GetActiveScene().name;
}
if (loadOnStart)
{
if (saveManager.SaveDataExists())
{
saveManager.Load();
}
}
}
protected virtual void Update()
{
var saveManager = FungusManager.Instance.SaveManager;
// Hide the Save and Load buttons if autosave is on
bool showSaveAndLoad = !autoSave;
if (saveButton.IsActive() != showSaveAndLoad)
{
saveButton.gameObject.SetActive(showSaveAndLoad);
loadButton.gameObject.SetActive(showSaveAndLoad);
}
if (showSaveAndLoad)
{
if (saveButton != null)
{
// Don't allow saving unless there's at least one save point in the history,
// This avoids the case where you could try to load a save data with 0 save points.
saveButton.interactable = saveManager.NumSavePoints > 0;
}
if (loadButton != null)
{
loadButton.interactable = saveManager.SaveDataExists();
}
}
if (rewindButton != null)
{
rewindButton.interactable = saveManager.NumSavePoints > 0;
}
if (forwardButton != null)
{
forwardButton.interactable = saveManager.NumRewoundSavePoints > 0;
}
if (debugView.enabled)
{
var debugText = debugView.GetComponentInChildren<Text>();
if (debugText != null)
{
debugText.text = saveManager.GetDebugInfo();
}
}
}
protected virtual void OnEnable()
{
SaveManagerSignals.OnSavePointAdded += OnSavePointAdded;
}
protected virtual void OnDisable()
{
SaveManagerSignals.OnSavePointAdded -= OnSavePointAdded;
}
protected virtual void OnSavePointAdded(string savePointKey, string savePointDescription)
{
var saveManager = FungusManager.Instance.SaveManager;
if (autoSave &&
saveManager.NumSavePoints > 0)
{
saveManager.Save();
}
}
protected void PlayClickSound()
{
if (clickAudioSource != null)
{
clickAudioSource.Play();
}
}
#region Public methods
/// <summary>
/// Toggles the expanded / collapsed state of the save menu.
/// Uses a tween to fade the menu UI in and out.
/// </summary>
public virtual void ToggleSaveMenu()
{
if (fadeTween != null)
{
LeanTween.cancel(fadeTween.id, true);
fadeTween = null;
}
if (saveMenuActive)
{
// Switch menu off
LeanTween.value(saveMenuGroup.gameObject, saveMenuGroup.alpha, 0f, 0.5f).setOnUpdate( (t) => {
saveMenuGroup.alpha = t;
}).setOnComplete( () => {
saveMenuGroup.alpha = 0f;
});
}
else
{
// Switch menu on
LeanTween.value(saveMenuGroup.gameObject, saveMenuGroup.alpha, 1f, 0.5f).setOnUpdate( (t) => {
saveMenuGroup.alpha = t;
}).setOnComplete( () => {
saveMenuGroup.alpha = 1f;
});
}
saveMenuActive = !saveMenuActive;
}
/// <summary>
/// Handler function called when the Save button is pressed.
/// </summary>
public virtual void Save()
{
var saveManager = FungusManager.Instance.SaveManager;
if (saveManager.NumSavePoints > 0)
{
PlayClickSound();
saveManager.Save();
}
}
/// <summary>
/// Handler function called when the Load button is pressed.
/// </summary>
public virtual void Load()
{
var saveManager = FungusManager.Instance.SaveManager;
if (saveManager.SaveDataExists())
{
PlayClickSound();
saveManager.Load();
}
}
/// <summary>
/// Handler function called when the Rewind button is pressed.
/// </summary>
public virtual void Rewind()
{
PlayClickSound();
var saveManager = FungusManager.Instance.SaveManager;
if (saveManager.NumSavePoints > 0)
{
saveManager.Rewind();
}
}
/// <summary>
/// Handler function called when the Fast Forward button is pressed.
/// </summary>
public virtual void FastForward()
{
PlayClickSound();
var saveManager = FungusManager.Instance.SaveManager;
if (saveManager.NumRewoundSavePoints > 0)
{
saveManager.FastForward();
}
}
/// <summary>
/// Handler function called when the Restart button is pressed.
/// </summary>
public virtual void Restart()
{
var saveManager = FungusManager.Instance.SaveManager;
if (string.IsNullOrEmpty(saveManager.StartScene))
{
Debug.LogError("No start scene specified");
return;
}
PlayClickSound();
// Reset the Save History for a new game
saveManager.ClearHistory();
if (restartDeletesSave)
{
saveManager.Delete();
}
SceneManager.LoadScene(saveManager.StartScene);
}
#endregion
}
}
#endif

12
Assets/Fungus/Scripts/Components/SaveMenu.cs.meta

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: abe25ebf9ddc8416ead6f30d4671fdbf
timeCreated: 1478863843
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

14
Assets/Fungus/Scripts/Components/SayDialog.cs

@ -37,6 +37,9 @@ namespace Fungus
[Tooltip("Adjust width of story text when Character Image is displayed (to avoid overlapping)")]
[SerializeField] protected bool fitTextWithImage = true;
[Tooltip("Close any other open Say Dialogs when this one is active")]
[SerializeField] protected bool closeOtherDialogs;
protected float startStoryTextWidth;
protected float startStoryTextInset;
@ -452,6 +455,17 @@ namespace Fungus
}
}
if (closeOtherDialogs)
{
for (int i = 0; i < activeSayDialogs.Count; i++)
{
var sd = activeSayDialogs[i];
if (sd.gameObject != gameObject)
{
sd.SetActive(false);
}
}
}
gameObject.SetActive(true);
this.fadeWhenDone = fadeWhenDone;

4
Assets/Fungus/Scripts/Editor/CallEditor.cs

@ -11,6 +11,7 @@ namespace Fungus.EditorUtils
{
protected SerializedProperty targetFlowchartProp;
protected SerializedProperty targetBlockProp;
protected SerializedProperty startLabelProp;
protected SerializedProperty startIndexProp;
protected SerializedProperty callModeProp;
@ -21,6 +22,7 @@ namespace Fungus.EditorUtils
targetFlowchartProp = serializedObject.FindProperty("targetFlowchart");
targetBlockProp = serializedObject.FindProperty("targetBlock");
startLabelProp = serializedObject.FindProperty("startLabel");
startIndexProp = serializedObject.FindProperty("startIndex");
callModeProp = serializedObject.FindProperty("callMode");
}
@ -50,6 +52,8 @@ namespace Fungus.EditorUtils
new GUIContent("<None>"),
flowchart);
EditorGUILayout.PropertyField(startLabelProp);
EditorGUILayout.PropertyField(startIndexProp);
}

54
Assets/Fungus/Scripts/Editor/EventHandlerEditor.cs

@ -9,6 +9,36 @@ namespace Fungus.EditorUtils
[CustomEditor (typeof(EventHandler), true)]
public class EventHandlerEditor : Editor
{
protected virtual void DrawProperties()
{
SerializedProperty iterator = serializedObject.GetIterator();
bool enterChildren = true;
while (iterator.NextVisible(enterChildren))
{
enterChildren = false;
if (iterator.name == "m_Script")
{
continue;
}
EditorGUILayout.PropertyField(iterator, true, new GUILayoutOption[0]);
}
}
protected virtual void DrawHelpBox()
{
EventHandler t = target as EventHandler;
EventHandlerInfoAttribute info = EventHandlerEditor.GetEventHandlerInfo(t.GetType());
if (info != null &&
info.HelpText.Length > 0)
{
EditorGUILayout.HelpBox(info.HelpText, MessageType.Info);
}
}
#region Public members
/// <summary>
/// Returns the class attribute info for an event handler class.
/// </summary>
@ -33,29 +63,13 @@ namespace Fungus.EditorUtils
// Doing so could cause block.commandList to contain null entries.
// To avoid this we manually display all properties, except for m_Script.
serializedObject.Update();
SerializedProperty iterator = serializedObject.GetIterator();
bool enterChildren = true;
while (iterator.NextVisible(enterChildren))
{
enterChildren = false;
if (iterator.name == "m_Script")
{
continue;
}
EditorGUILayout.PropertyField(iterator, true, new GUILayoutOption[0]);
}
EventHandler t = target as EventHandler;
EventHandlerInfoAttribute info = EventHandlerEditor.GetEventHandlerInfo(t.GetType());
if (info != null &&
info.HelpText.Length > 0)
{
EditorGUILayout.HelpBox(info.HelpText, MessageType.Info);
}
DrawProperties();
DrawHelpBox();
serializedObject.ApplyModifiedProperties();
}
#endregion
}
}

6
Assets/Fungus/Scripts/Editor/MenuEditor.cs

@ -44,9 +44,9 @@ namespace Fungus.EditorUtils
EditorGUILayout.PropertyField(descriptionProp);
BlockEditor.BlockField(targetBlockProp,
new GUIContent("Target Block", "Block to call when option is selected"),
new GUIContent("<None>"),
flowchart);
new GUIContent("Target Block", "Block to call when option is selected"),
new GUIContent("<None>"),
flowchart);
EditorGUILayout.PropertyField(hideIfVisitedProp);
EditorGUILayout.PropertyField(interactableProp);

34
Assets/Fungus/Scripts/Editor/SaveDataEditor.cs

@ -0,0 +1,34 @@
// This code is part of the Fungus library (http://fungusgames.com) maintained by Chris Gregan (http://twitter.com/gofungus).
// It is released for free under the MIT open source license (https://github.com/snozbot/fungus/blob/master/LICENSE)
#if UNITY_5_3_OR_NEWER
using UnityEngine;
using UnityEditor;
using Rotorz.ReorderableList;
namespace Fungus.EditorUtils
{
[CustomEditor (typeof(SaveData), true)]
public class SaveDataEditor : Editor
{
protected SerializedProperty flowchartsProp;
protected virtual void OnEnable()
{
flowchartsProp = serializedObject.FindProperty("flowcharts");
}
public override void OnInspectorGUI()
{
serializedObject.Update();
ReorderableListGUI.Title("Flowcharts");
ReorderableListGUI.ListField(flowchartsProp);
serializedObject.ApplyModifiedProperties();
}
}
}
#endif

12
Assets/Fungus/Scripts/Editor/SaveDataEditor.cs.meta

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 395934d0b0e6a48a396a25348aeaade5
timeCreated: 1484049679
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

22
Assets/Fungus/Scripts/Editor/SaveMenuItems.cs

@ -0,0 +1,22 @@
// This code is part of the Fungus library (http://fungusgames.com) maintained by Chris Gregan (http://twitter.com/gofungus).
// It is released for free under the MIT open source license (https://github.com/snozbot/fungus/blob/master/LICENSE)
using UnityEditor;
namespace Fungus.EditorUtils
{
public class SaveMenuItems
{
[MenuItem("Tools/Fungus/Create/Save Menu", false, 1100)]
static void CreateSaveMenu()
{
FlowchartMenuItems.SpawnPrefab("SaveMenu");
}
[MenuItem("Tools/Fungus/Create/Save Data", false, 1101)]
static void CreateSaveData()
{
FlowchartMenuItems.SpawnPrefab("SaveData");
}
}
}

8
Assets/Fungus/Scripts/Editor/SaveMenuItems.cs.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ecf88c3abcff64465bded608b8babf02
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

2
Assets/Fungus/Scripts/EventHandlers/FlowchartEnabled.cs

@ -8,7 +8,7 @@ namespace Fungus
/// <summary>
/// The block will execute when the Flowchart game object is enabled.
/// </summary>
[EventHandlerInfo("",
[EventHandlerInfo("Scene",
"Flowchart Enabled",
"The block will execute when the Flowchart game object is enabled.")]
[AddComponentMenu("")]

2
Assets/Fungus/Scripts/EventHandlers/MessageReceived.cs

@ -8,7 +8,7 @@ namespace Fungus
/// <summary>
/// The block will execute when the specified message is received from a Send Message command.
/// </summary>
[EventHandlerInfo("",
[EventHandlerInfo("Scene",
"Message Received",
"The block will execute when the specified message is received from a Send Message command.")]
[AddComponentMenu("")]

45
Assets/Fungus/Scripts/EventHandlers/SavePointLoaded.cs

@ -0,0 +1,45 @@
// This code is part of the Fungus library (http://fungusgames.com) maintained by Chris Gregan (http://twitter.com/gofungus).
// It is released for free under the MIT open source license (https://github.com/snozbot/fungus/blob/master/LICENSE)
using UnityEngine;
using System.Collections.Generic;
namespace Fungus
{
[EventHandlerInfo("Scene",
"Save Point Loaded",
"Execute this block when a saved point is loaded. Use the 'new_game' key to handle game start.")]
public class SavePointLoaded : EventHandler
{
[Tooltip("Block will execute if the Save Key of the loaded save point matches this save key.")]
[SerializeField] protected List<string> savePointKeys = new List<string>();
protected void OnSavePointLoaded(string _savePointKey)
{
for (int i = 0; i < savePointKeys.Count; i++)
{
var key = savePointKeys[i];
if (string.Compare(key, _savePointKey, true) == 0)
{
ExecuteBlock();
break;
}
}
}
#region Public methods
public static void NotifyEventHandlers(string _savePointKey)
{
// Fire any matching SavePointLoaded event handler with matching save key.
var eventHandlers = Object.FindObjectsOfType<SavePointLoaded>();
for (int i = 0; i < eventHandlers.Length; i++)
{
var eventHandler = eventHandlers[i];
eventHandler.OnSavePointLoaded(_savePointKey);
}
}
#endregion
}
}

12
Assets/Fungus/Scripts/EventHandlers/SavePointLoaded.cs.meta

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 9ca33a026786245d4b10323b87e84d5f
timeCreated: 1479142351
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

30
Assets/Fungus/Scripts/Signals/SaveManagerSignals.cs

@ -0,0 +1,30 @@
// This code is part of the Fungus library (http://fungusgames.com) maintained by Chris Gregan (http://twitter.com/gofungus).
// It is released for free under the MIT open source license (https://github.com/snozbot/fungus/blob/master/LICENSE)
namespace Fungus
{
/// <summary>
/// Save manager signalling system.
/// You can use this to be notified about various events in the save game system.
/// </summary>
public static class SaveManagerSignals
{
#region Public members
/// <summary>
/// SavePointLoaded signal. Sent just after a SavePoint is loaded.
/// </summary>
public static event SavePointLoadedHandler OnSavePointLoaded;
public delegate void SavePointLoadedHandler(string savePointKey);
public static void DoSavePointLoaded(string savePointKey) { if (OnSavePointLoaded != null) OnSavePointLoaded(savePointKey); }
/// <summary>
/// SavePointAdded signal. Sent when a new save point is added to the save history (typically via the Save Point command).
/// </summary>
public static event SavePointAddedHandler OnSavePointAdded;
public delegate void SavePointAddedHandler(string savePointKey, string savePointDescription);
public static void DoSavePointAdded(string savePointKey, string savePointDescription) { if (OnSavePointAdded != null) OnSavePointAdded(savePointKey, savePointDescription); }
#endregion
}
}

12
Assets/Fungus/Scripts/Signals/SaveManagerSignals.cs.meta

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 2b71673fcda1a4fd4946bd58cebf3465
timeCreated: 1480691177
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

216
Assets/Fungus/Scripts/Utils/FlowchartData.cs

@ -0,0 +1,216 @@
// This code is part of the Fungus library (http://fungusgames.com) maintained by Chris Gregan (http://twitter.com/gofungus).
// It is released for free under the MIT open source license (https://github.com/snozbot/fungus/blob/master/LICENSE)
using System.Collections.Generic;
using UnityEngine;
namespace Fungus
{
/// <summary>
/// Serializable container for a string variable.
/// </summary>
[System.Serializable]
public class StringVar
{
[SerializeField] protected string key;
[SerializeField] protected string value;
#region Public methods
public string Key { get { return key; } set { key = value; } }
public string Value { get { return value; } set { this.value = value; } }
#endregion
}
/// <summary>
/// Serializable container for an integer variable.
/// </summary>
[System.Serializable]
public class IntVar
{
[SerializeField] protected string key;
[SerializeField] protected int value;
#region Public methods
public string Key { get { return key; } set { key = value; } }
public int Value { get { return value; } set { this.value = value; } }
#endregion
}
/// <summary>
/// Serializable container for a float variable.
/// </summary>
[System.Serializable]
public class FloatVar
{
[SerializeField] protected string key;
[SerializeField] protected float value;
#region Public methods
public string Key { get { return key; } set { key = value; } }
public float Value { get { return value; } set { this.value = value; } }
#endregion
}
/// <summary>
/// Serializable container for a boolean variable.
/// </summary>
[System.Serializable]
public class BoolVar
{
[SerializeField] protected string key;
[SerializeField] protected bool value;
#region Public methods
public string Key { get { return key; } set { key = value; } }
public bool Value { get { return value; } set { this.value = value; } }
#endregion
}
/// <summary>
/// Serializable container for encoding the state of a Flowchart's variables.
/// </summary>
[System.Serializable]
public class FlowchartData
{
[SerializeField] protected string flowchartName;
[SerializeField] protected List<StringVar> stringVars = new List<StringVar>();
[SerializeField] protected List<IntVar> intVars = new List<IntVar>();
[SerializeField] protected List<FloatVar> floatVars = new List<FloatVar>();
[SerializeField] protected List<BoolVar> boolVars = new List<BoolVar>();
#region Public methods
/// <summary>
/// Gets or sets the name of the encoded Flowchart.
/// </summary>
public string FlowchartName { get { return flowchartName; } set { flowchartName = value; } }
/// <summary>
/// Gets or sets the list of encoded string variables.
/// </summary>
public List<StringVar> StringVars { get { return stringVars; } set { stringVars = value; } }
/// <summary>
/// Gets or sets the list of encoded integer variables.
/// </summary>
public List<IntVar> IntVars { get { return intVars; } set { intVars = value; } }
/// <summary>
/// Gets or sets the list of encoded float variables.
/// </summary>
public List<FloatVar> FloatVars { get { return floatVars; } set { floatVars = value; } }
/// <summary>
/// Gets or sets the list of encoded boolean variables.
/// </summary>
public List<BoolVar> BoolVars { get { return boolVars; } set { boolVars = value; } }
/// <summary>
/// Encodes the data in a Flowchart into a structure that can be stored by the save system.
/// </summary>
public static FlowchartData Encode(Flowchart flowchart)
{
var flowchartData = new FlowchartData();
flowchartData.FlowchartName = flowchart.name;
for (int i = 0; i < flowchart.Variables.Count; i++)
{
var v = flowchart.Variables[i];
// Save string
var stringVariable = v as StringVariable;
if (stringVariable != null)
{
var d = new StringVar();
d.Key = stringVariable.Key;
d.Value = stringVariable.Value;
flowchartData.StringVars.Add(d);
}
// Save int
var intVariable = v as IntegerVariable;
if (intVariable != null)
{
var d = new IntVar();
d.Key = intVariable.Key;
d.Value = intVariable.Value;
flowchartData.IntVars.Add(d);
}
// Save float
var floatVariable = v as FloatVariable;
if (floatVariable != null)
{
var d = new FloatVar();
d.Key = floatVariable.Key;
d.Value = floatVariable.Value;
flowchartData.FloatVars.Add(d);
}
// Save bool
var boolVariable = v as BooleanVariable;
if (boolVariable != null)
{
var d = new BoolVar();
d.Key = boolVariable.Key;
d.Value = boolVariable.Value;
flowchartData.BoolVars.Add(d);
}
}
return flowchartData;
}
/// <summary>
/// Decodes a FlowchartData object and uses it to restore the state of a Flowchart in the scene.
/// </summary>
public static void Decode(FlowchartData flowchartData)
{
var go = GameObject.Find(flowchartData.FlowchartName);
if (go == null)
{
Debug.LogError("Failed to find flowchart object specified in save data");
return;
}
var flowchart = go.GetComponent<Flowchart>();
if (flowchart == null)
{
Debug.LogError("Failed to find flowchart object specified in save data");
return;
}
for (int i = 0; i < flowchartData.BoolVars.Count; i++)
{
var boolVar = flowchartData.BoolVars[i];
flowchart.SetBooleanVariable(boolVar.Key, boolVar.Value);
}
for (int i = 0; i < flowchartData.IntVars.Count; i++)
{
var intVar = flowchartData.IntVars[i];
flowchart.SetIntegerVariable(intVar.Key, intVar.Value);
}
for (int i = 0; i < flowchartData.FloatVars.Count; i++)
{
var floatVar = flowchartData.FloatVars[i];
flowchart.SetFloatVariable(floatVar.Key, floatVar.Value);
}
for (int i = 0; i < flowchartData.StringVars.Count; i++)
{
var stringVar = flowchartData.StringVars[i];
flowchart.SetStringVariable(stringVar.Key, stringVar.Value);
}
}
#endregion
}
}

12
Assets/Fungus/Scripts/Utils/FlowchartData.cs.meta

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 07443f90b887a47fb846500fe5ce3840
timeCreated: 1478698399
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

11
Assets/Fungus/Scripts/Utils/FungusConstants.cs

@ -27,8 +27,19 @@ namespace Fungus
/// </summary>
public const string DefaultBlockName = "New Block";
/// <summary>
/// The default choice block color.
/// </summary>
public static Color DefaultChoiceBlockTint = new Color(1.0f, 0.627f, 0.313f, 1.0f);
/// <summary>
/// The default event block color.
/// </summary>
public static Color DefaultEventBlockTint = new Color(0.784f, 0.882f, 1.0f, 1.0f);
/// <summary>
/// The default process block color.
/// </summary>
public static Color DefaultProcessBlockTint = new Color(1.0f, 0.882f, 0.0f, 1.0f);
#endregion

45
Assets/Fungus/Scripts/Utils/SaveDataItem.cs

@ -0,0 +1,45 @@
// This code is part of the Fungus library (http://fungusgames.com) maintained by Chris Gregan (http://twitter.com/gofungus).
// It is released for free under the MIT open source license (https://github.com/snozbot/fungus/blob/master/LICENSE)
using UnityEngine;
namespace Fungus
{
/// <summary>
/// A container for a single unity of saved data.
/// The data and its associated type are stored as string properties.
/// The data would typically be a JSON string representing a saved object.
/// </summary>
[System.Serializable]
public class SaveDataItem
{
[SerializeField] protected string dataType = "";
[SerializeField] protected string data = "";
#region Public methods
/// <summary>
/// Gets the type of the data.
/// </summary>
public virtual string DataType { get { return dataType; } }
/// <summary>
/// Gets the data.
/// </summary>
public virtual string Data { get { return data; } }
/// <summary>
/// Factory method to create a new SaveDataItem.
/// </summary>
public static SaveDataItem Create(string dataType, string data)
{
var item = new SaveDataItem();
item.dataType = dataType;
item.data = data;
return item;
}
#endregion
}
}

12
Assets/Fungus/Scripts/Utils/SaveDataItem.cs.meta

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 67dfa5e8ded9244f98136428ed129403
timeCreated: 1484649086
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

132
Assets/Fungus/Scripts/Utils/SaveHistory.cs

@ -0,0 +1,132 @@
// This code is part of the Fungus library (http://fungusgames.com) maintained by Chris Gregan (http://twitter.com/gofungus).
// It is released for free under the MIT open source license (https://github.com/snozbot/fungus/blob/master/LICENSE)
#if UNITY_5_3_OR_NEWER
using UnityEngine;
using System.Collections.Generic;
using UnityEngine.SceneManagement;
namespace Fungus
{
/// <summary>
/// The Save History is a list of previously created Save Points, sorted chronologically.
/// </summary>
[System.Serializable]
public class SaveHistory
{
/// <summary>
/// Version number of current save data format.
/// </summary>
protected const int SaveDataVersion = 1;
[SerializeField] protected int version = SaveDataVersion;
[SerializeField] protected List<string> savePoints = new List<string>();
[SerializeField] protected List<string> rewoundSavePoints = new List<string>();
#region Public methods
/// <summary>
/// Returns the number of Save Points in the Save History.
/// </summary>
public int NumSavePoints { get { return savePoints.Count; } }
/// <summary>
/// Returns the current number of rewound Save Points in the Save History.
/// </summary>
public int NumRewoundSavePoints { get { return rewoundSavePoints.Count; } }
/// <summary>
/// Creates a new Save Point using a key and description, and adds it to the Save History.
/// </summary>
public void AddSavePoint(string savePointKey, string savePointDescription)
{
// Creating a new Save Point invalidates all rewound Save Points, so delete them.
ClearRewoundSavePoints();
string sceneName = SceneManager.GetActiveScene().name;
var savePointData = SavePointData.Encode(savePointKey, savePointDescription, sceneName);
savePoints.Add(savePointData);
}
/// <summary>
/// Rewinds to the previous Save Point in the Save History.
/// The latest Save Point is moved to a seperate list of rewound save points.
/// </summary>
public void Rewind()
{
if (savePoints.Count > 0)
{
rewoundSavePoints.Add(savePoints[savePoints.Count - 1]);
savePoints.RemoveAt(savePoints.Count - 1);
}
}
/// <summary>
/// Fast forwards to the next Save Point in the Save History.
/// The most recently rewound Save Point is moved back to the main list of save points.
/// </summary>
public void FastForward()
{
if (rewoundSavePoints.Count > 0)
{
savePoints.Add(rewoundSavePoints[rewoundSavePoints.Count - 1]);
rewoundSavePoints.RemoveAt(rewoundSavePoints.Count - 1);
}
}
/// <summary>
/// Loads the latest Save Point.
/// </summary>
public void LoadLatestSavePoint()
{
if (savePoints.Count > 0)
{
var savePointData = savePoints[savePoints.Count - 1];
SavePointData.Decode(savePointData);
}
}
/// <summary>
/// Clears all Save Points.
/// </summary>
public void Clear()
{
savePoints.Clear();
rewoundSavePoints.Clear();
}
/// <summary>
/// Clears rewound Save Points only. The main Save Point list is not changed.
/// </summary>
public void ClearRewoundSavePoints()
{
rewoundSavePoints.Clear();
}
public virtual string GetDebugInfo()
{
string debugInfo = "Save points:\n";
foreach (var savePoint in savePoints)
{
debugInfo += savePoint.Substring(0, savePoint.IndexOf(',')).Replace("\n", "").Replace("{", "").Replace("}","") + "\n";
}
debugInfo += "Rewound points:\n";
foreach (var savePoint in rewoundSavePoints)
{
debugInfo += savePoint.Substring(0, savePoint.IndexOf(',')).Replace("\n", "").Replace("{", "").Replace("}","") + "\n";
}
return debugInfo;
}
#endregion
}
}
#endif

12
Assets/Fungus/Scripts/Utils/SaveHistory.cs.meta

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: fd859426b9f7445b5a1d7281f4943bb8
timeCreated: 1480422606
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

117
Assets/Fungus/Scripts/Utils/SavePointData.cs

@ -0,0 +1,117 @@
// This code is part of the Fungus library (http://fungusgames.com) maintained by Chris Gregan (http://twitter.com/gofungus).
// It is released for free under the MIT open source license (https://github.com/snozbot/fungus/blob/master/LICENSE)
#if UNITY_5_3_OR_NEWER
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.Events;
namespace Fungus
{
/// <summary>
/// Serializable container for a Save Point's data.
/// All data is stored as strings, and the only concrete game class it depends on is the SaveData component.
/// </summary>
[System.Serializable]
public class SavePointData
{
[SerializeField] protected string savePointKey;
[SerializeField] protected string savePointDescription;
[SerializeField] protected string sceneName;
[SerializeField] protected List<SaveDataItem> saveDataItems = new List<SaveDataItem>();
protected static SavePointData Create(string _savePointKey, string _savePointDescription, string _sceneName)
{
var savePointData = new SavePointData();
savePointData.savePointKey = _savePointKey;
savePointData.savePointDescription = _savePointDescription;
savePointData.sceneName = _sceneName;
return savePointData;
}
#region Public methods
/// <summary>
/// Gets or sets the unique key for the Save Point.
/// </summary>
public string SavePointKey { get { return savePointKey; } set { savePointKey = value; } }
/// <summary>
/// Gets or sets the description for the Save Point.
/// </summary>
public string SavePointDescription { get { return savePointDescription; } set { savePointDescription = value; } }
/// <summary>
/// Gets or sets the scene name associated with the Save Point.
/// </summary>
public string SceneName { get { return sceneName; } set { sceneName = value; } }
/// <summary>
/// Gets the list of save data items.
/// </summary>
/// <value>The save data items.</value>
public List<SaveDataItem> SaveDataItems { get { return saveDataItems; } }
/// <summary>
/// Encodes a new Save Point to data and converts it to JSON text format.
/// </summary>
public static string Encode(string _savePointKey, string _savePointDescription, string _sceneName)
{
var savePointData = Create(_savePointKey, _savePointDescription, _sceneName);
// Look for a SaveData component in the scene to populate the save data items.
var saveData = GameObject.FindObjectOfType<SaveData>();
if (saveData != null)
{
saveData.Encode(savePointData.SaveDataItems);
}
return JsonUtility.ToJson(savePointData, true);
}
/// <summary>
/// Decodes a Save Point from JSON text format and loads it.
/// </summary>
public static void Decode(string saveDataJSON)
{
var savePointData = JsonUtility.FromJson<SavePointData>(saveDataJSON);
UnityAction<Scene, LoadSceneMode> onSceneLoadedAction = null;
onSceneLoadedAction = (scene, mode) => {
// Additive scene loads and non-matching scene loads could happen if the client is using the
// SceneManager directly. We just ignore these events and hope they know what they're doing!
if (mode == LoadSceneMode.Additive ||
scene.name != savePointData.SceneName)
{
return;
}
SceneManager.sceneLoaded -= onSceneLoadedAction;
// Look for a SaveData component in the scene to process the save data items.
var saveData = GameObject.FindObjectOfType<SaveData>();
if (saveData != null)
{
saveData.Decode(savePointData.SaveDataItems);
}
SaveManagerSignals.DoSavePointLoaded(savePointData.savePointKey);
};
SceneManager.sceneLoaded += onSceneLoadedAction;
SceneManager.LoadScene(savePointData.SceneName);
}
#endregion
}
}
#endif

12
Assets/Fungus/Scripts/Utils/SavePointData.cs.meta

@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: d19fe746c09ac44e2bf310e6a1350b8c
timeCreated: 1478698399
licenseType: Free
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

BIN
Assets/Fungus/Textures/GreyButton.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 414 B

84
Assets/Fungus/Textures/GreyButton.png.meta

@ -0,0 +1,84 @@
fileFormatVersion: 2
guid: 9bdedfa4650174106a3115624f193b99
timeCreated: 1484222376
licenseType: Free
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
filterMode: -1
aniso: -1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 3, y: 3, z: 3, w: 3}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 128
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Standalone
maxTextureSize: 128
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: WebGL
maxTextureSize: 128
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

BIN
Assets/Fungus/Textures/rewind.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

84
Assets/Fungus/Textures/rewind.png.meta

@ -0,0 +1,84 @@
fileFormatVersion: 2
guid: 62573ea76cbf34643bf28a259a6c901c
timeCreated: 1484222702
licenseType: Free
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
filterMode: -1
aniso: -1
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: Standalone
maxTextureSize: 2048
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
- buildTarget: WebGL
maxTextureSize: 2048
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

BIN
Assets/Fungus/Textures/settings.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

59
Assets/Fungus/Textures/settings.png.meta

@ -0,0 +1,59 @@
fileFormatVersion: 2
guid: 8d3c80dd0c2904cdbb745cf481348a76
timeCreated: 1480950906
licenseType: Free
TextureImporter:
fileIDToRecycleName: {}
serializedVersion: 2
mipmaps:
mipMapMode: 0
enableMipMap: 1
linearTexture: 0
correctGamma: 0
fadeOut: 0
borderMipMap: 0
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 0
cubemapConvolution: 0
cubemapConvolutionSteps: 7
cubemapConvolutionExponent: 1.5
seamlessCubemap: 0
textureFormat: -3
maxTextureSize: 2048
textureSettings:
filterMode: -1
aniso: 16
mipBias: -1
wrapMode: 1
nPOTScale: 0
lightmap: 0
rGBM: 0
compressionQuality: 50
allowsAlphaSplitting: 0
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
buildTargetSettings: []
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:

9
Assets/FungusExamples/SaveGame.meta

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 02853ba7546b74a7cb03cdd14f1ab055
folderAsset: yes
timeCreated: 1478862076
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

4625
Assets/FungusExamples/SaveGame/SaveGame.unity

File diff suppressed because it is too large Load Diff

8
Assets/FungusExamples/SaveGame/SaveGame.unity.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a440424aaf73a4ff3bf88e9d1eb3a43c
timeCreated: 1480421523
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

351
Assets/Tests/Flow/FlowTests.unity

@ -13,7 +13,7 @@ SceneSettings:
--- !u!104 &2
RenderSettings:
m_ObjectHideFlags: 0
serializedVersion: 6
serializedVersion: 7
m_Fog: 0
m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
m_FogMode: 3
@ -37,12 +37,12 @@ RenderSettings:
m_ReflectionIntensity: 1
m_CustomReflection: {fileID: 0}
m_Sun: {fileID: 0}
m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1}
--- !u!157 &3
LightmapSettings:
m_ObjectHideFlags: 0
serializedVersion: 6
serializedVersion: 7
m_GIWorkflowMode: 1
m_LightmapsMode: 1
m_GISettings:
serializedVersion: 2
m_BounceScale: 1
@ -53,17 +53,22 @@ LightmapSettings:
m_EnableBakedLightmaps: 0
m_EnableRealtimeLightmaps: 0
m_LightmapEditorSettings:
serializedVersion: 3
serializedVersion: 4
m_Resolution: 2
m_BakeResolution: 40
m_TextureWidth: 1024
m_TextureHeight: 1024
m_AO: 0
m_AOMaxDistance: 1
m_Padding: 2
m_CompAOExponent: 0
m_CompAOExponentDirect: 0
m_Padding: 2
m_LightmapParameters: {fileID: 0}
m_LightmapsBakeMode: 1
m_TextureCompression: 1
m_DirectLightInLightProbes: 1
m_FinalGather: 0
m_FinalGatherFiltering: 1
m_FinalGatherRayCount: 1024
m_ReflectionCompression: 2
m_LightingDataAsset: {fileID: 0}
@ -244,7 +249,7 @@ GameObject:
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
m_IsActive: 0
--- !u!114 &730370421
MonoBehaviour:
m_ObjectHideFlags: 0
@ -442,7 +447,6 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
itemId: 4
errorMessage:
indentLevel: 0
--- !u!114 &897339007
MonoBehaviour:
@ -456,7 +460,6 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
itemId: 3
errorMessage:
indentLevel: 0
failMessage:
--- !u!114 &897339008
@ -471,10 +474,12 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
itemId: 2
errorMessage:
indentLevel: 0
targetFlowchart: {fileID: 0}
targetBlock: {fileID: 897339009}
startLabel:
stringRef: {fileID: 0}
stringVal:
startIndex: 1
callMode: 0
--- !u!114 &897339009
@ -494,6 +499,8 @@ MonoBehaviour:
y: 70
width: 120
height: 40
tint: {r: 1, g: 1, b: 1, a: 1}
useCustomTint: 0
itemId: 1
blockName: OtherBlock
description:
@ -514,6 +521,7 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
parentBlock: {fileID: 897339011}
waitForFrames: 1
--- !u!114 &897339011
MonoBehaviour:
m_ObjectHideFlags: 2
@ -532,6 +540,8 @@ MonoBehaviour:
y: 70
width: 120
height: 40
tint: {r: 1, g: 1, b: 1, a: 1}
useCustomTint: 0
itemId: 0
blockName: Start
description:
@ -562,7 +572,7 @@ MonoBehaviour:
y: -350
width: 1121
height: 869
selectedBlock: {fileID: 0}
selectedBlocks: []
selectedCommands: []
variables: []
description: "Test using the call index property to call \na specific command in
@ -574,6 +584,59 @@ MonoBehaviour:
localizationId:
showLineNumbers: 0
hideCommands: []
luaEnvironment: {fileID: 0}
luaBindingName: flowchart
--- !u!1 &919683558
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
serializedVersion: 4
m_Component:
- 4: {fileID: 919683560}
- 114: {fileID: 919683559}
m_Layer: 0
m_Name: CallWithLabelTest
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 0
--- !u!114 &919683559
MonoBehaviour:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 919683558}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: b1dba0b27b0864740a8720e920aa88c0, type: 3}
m_Name:
m_EditorClassIdentifier:
timeout: 5
ignored: 0
succeedAfterAllAssertionsAreExecuted: 0
expectException: 0
expectedExceptionList:
succeedWhenExceptionIsThrown: 0
includedPlatforms: -1
platformsToIgnore: []
dynamic: 0
dynamicTypeName:
--- !u!4 &919683560
Transform:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 919683558}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_Children:
- {fileID: 2121984966}
m_Father: {fileID: 0}
m_RootOrder: 7
--- !u!1 &1040991508
GameObject:
m_ObjectHideFlags: 0
@ -617,7 +680,6 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
itemId: 1
errorMessage:
indentLevel: 0
--- !u!114 &1040991511
MonoBehaviour:
@ -637,6 +699,8 @@ MonoBehaviour:
y: 70
width: 120
height: 40
tint: {r: 1, g: 1, b: 1, a: 1}
useCustomTint: 0
itemId: 0
blockName: DoTest
description:
@ -667,7 +731,7 @@ MonoBehaviour:
y: -340
width: 1114
height: 859
selectedBlock: {fileID: 1040991511}
selectedBlocks: []
selectedCommands:
- {fileID: 1040991510}
variables: []
@ -679,6 +743,8 @@ MonoBehaviour:
localizationId:
showLineNumbers: 0
hideCommands: []
luaEnvironment: {fileID: 0}
luaBindingName: flowchart
--- !u!1 &1220080381
GameObject:
m_ObjectHideFlags: 0
@ -813,7 +879,6 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
itemId: 4
errorMessage:
indentLevel: 0
--- !u!114 &1253352150
MonoBehaviour:
@ -827,7 +892,6 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
itemId: 3
errorMessage:
indentLevel: 0
failMessage:
--- !u!114 &1253352151
@ -842,7 +906,6 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
itemId: 2
errorMessage:
indentLevel: 0
key: MyLabel
--- !u!114 &1253352152
@ -857,7 +920,6 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
itemId: 1
errorMessage:
indentLevel: 0
_targetLabel:
stringRef: {fileID: 0}
@ -876,6 +938,7 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
parentBlock: {fileID: 1253352154}
waitForFrames: 1
--- !u!114 &1253352154
MonoBehaviour:
m_ObjectHideFlags: 2
@ -894,6 +957,8 @@ MonoBehaviour:
y: 70
width: 120
height: 40
tint: {r: 1, g: 1, b: 1, a: 1}
useCustomTint: 0
itemId: 0
blockName: Start
description:
@ -916,18 +981,18 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
version: 1
scrollPos: {x: 0, y: 0}
scrollPos: {x: 3.562703, y: 1.8540598}
variablesScrollPos: {x: 0, y: 0}
variablesExpanded: 1
blockViewHeight: 400
zoom: 1
zoom: 0.98802704
scrollViewRect:
serializedVersion: 2
x: -343
y: -340
width: 1114
height: 859
selectedBlock: {fileID: 0}
x: -350
y: -350
width: 1121
height: 869
selectedBlocks: []
selectedCommands: []
variables: []
description: Tests if jumping to a label works correctly
@ -938,6 +1003,8 @@ MonoBehaviour:
localizationId:
showLineNumbers: 0
hideCommands: []
luaEnvironment: {fileID: 0}
luaBindingName: flowchart
--- !u!1 &1501994597
GameObject:
m_ObjectHideFlags: 0
@ -1185,7 +1252,6 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: ba19c26c1ba7243d2b57ebc4329cc7c6, type: 3}
m_Name:
m_EditorClassIdentifier:
remoteDebugger: 0
--- !u!114 &1601427684
MonoBehaviour:
m_ObjectHideFlags: 0
@ -1263,7 +1329,6 @@ MonoBehaviour:
executeAfterFrames: 1
repeatExecuteFrame: 1
repeatEveryFrame: 1
hasFailed: 0
executeMethods: 2
executeMethodName: OnExecute
--- !u!1 &1873336849
@ -1293,7 +1358,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 61dddfdc5e0e44ca298d8f46f7f5a915, type: 3}
m_Name:
m_EditorClassIdentifier:
selectedFlowchart: {fileID: 1253352155}
selectedFlowchart: {fileID: 2121984976}
--- !u!4 &1873336851
Transform:
m_ObjectHideFlags: 1
@ -1360,3 +1425,237 @@ Transform:
- {fileID: 1601427681}
m_Father: {fileID: 0}
m_RootOrder: 3
--- !u!1 &2121984965
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 142980, guid: 5e7fbc8d4eb714b279eeeef2262c1e1a, type: 2}
m_PrefabInternal: {fileID: 0}
serializedVersion: 4
m_Component:
- 4: {fileID: 2121984966}
- 114: {fileID: 2121984976}
- 114: {fileID: 2121984975}
- 114: {fileID: 2121984974}
- 114: {fileID: 2121984973}
- 114: {fileID: 2121984972}
- 114: {fileID: 2121984971}
- 114: {fileID: 2121984970}
- 114: {fileID: 2121984969}
- 114: {fileID: 2121984968}
- 114: {fileID: 2121984967}
m_Layer: 0
m_Name: Flowchart
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &2121984966
Transform:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 467082, guid: 5e7fbc8d4eb714b279eeeef2262c1e1a, type: 2}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 2121984965}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_Children: []
m_Father: {fileID: 919683560}
m_RootOrder: 0
--- !u!114 &2121984967
MonoBehaviour:
m_ObjectHideFlags: 2
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 2121984965}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5f1ca510a57aa47568a5e4ee558ff41f, type: 3}
m_Name:
m_EditorClassIdentifier:
itemId: 7
indentLevel: 0
--- !u!114 &2121984968
MonoBehaviour:
m_ObjectHideFlags: 2
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 2121984965}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4920f47cde1a84b11ad07b7317568494, type: 3}
m_Name:
m_EditorClassIdentifier:
itemId: 6
indentLevel: 0
--- !u!114 &2121984969
MonoBehaviour:
m_ObjectHideFlags: 2
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 2121984965}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 2dcb71131f45b47fead560a97ef55f1c, type: 3}
m_Name:
m_EditorClassIdentifier:
itemId: 5
indentLevel: 0
failMessage:
--- !u!114 &2121984970
MonoBehaviour:
m_ObjectHideFlags: 2
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 2121984965}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: ea4da378c47144a86979765ac5e9690c, type: 3}
m_Name:
m_EditorClassIdentifier:
itemId: 4
indentLevel: 0
key: LabelB
--- !u!114 &2121984971
MonoBehaviour:
m_ObjectHideFlags: 2
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 2121984965}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: ea4da378c47144a86979765ac5e9690c, type: 3}
m_Name:
m_EditorClassIdentifier:
itemId: 3
indentLevel: 0
key: LabelA
--- !u!114 &2121984972
MonoBehaviour:
m_ObjectHideFlags: 2
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 2121984965}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 050fb9e6e72f442b3b883da8a965bdeb, type: 3}
m_Name:
m_EditorClassIdentifier:
itemId: 2
indentLevel: 0
targetFlowchart: {fileID: 0}
targetBlock: {fileID: 2121984973}
startLabel:
stringRef: {fileID: 0}
stringVal: LabelB
startIndex: 0
callMode: 0
--- !u!114 &2121984973
MonoBehaviour:
m_ObjectHideFlags: 2
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 2121984965}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 3d3d73aef2cfc4f51abf34ac00241f60, type: 3}
m_Name:
m_EditorClassIdentifier:
nodeRect:
serializedVersion: 2
x: 258
y: 69
width: 120
height: 40
tint: {r: 1, g: 1, b: 1, a: 1}
useCustomTint: 0
itemId: 1
blockName: CallTarget
description:
eventHandler: {fileID: 0}
commandList:
- {fileID: 2121984971}
- {fileID: 2121984969}
- {fileID: 2121984967}
- {fileID: 2121984970}
- {fileID: 2121984968}
--- !u!114 &2121984974
MonoBehaviour:
m_ObjectHideFlags: 2
m_PrefabParentObject: {fileID: 11462346, guid: 5e7fbc8d4eb714b279eeeef2262c1e1a,
type: 2}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 2121984965}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d2f6487d21a03404cb21b245f0242e79, type: 3}
m_Name:
m_EditorClassIdentifier:
parentBlock: {fileID: 2121984975}
waitForFrames: 1
--- !u!114 &2121984975
MonoBehaviour:
m_ObjectHideFlags: 2
m_PrefabParentObject: {fileID: 11433304, guid: 5e7fbc8d4eb714b279eeeef2262c1e1a,
type: 2}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 2121984965}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 3d3d73aef2cfc4f51abf34ac00241f60, type: 3}
m_Name:
m_EditorClassIdentifier:
nodeRect:
serializedVersion: 2
x: 68
y: 70
width: 120
height: 40
tint: {r: 1, g: 1, b: 1, a: 1}
useCustomTint: 0
itemId: 0
blockName: Start
description:
eventHandler: {fileID: 2121984974}
commandList:
- {fileID: 2121984972}
--- !u!114 &2121984976
MonoBehaviour:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 11430050, guid: 5e7fbc8d4eb714b279eeeef2262c1e1a,
type: 2}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 2121984965}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 7a334fe2ffb574b3583ff3b18b4792d3, type: 3}
m_Name:
m_EditorClassIdentifier:
version: 1
scrollPos: {x: 1.7744522, y: -1.1711906}
variablesScrollPos: {x: 0, y: 0}
variablesExpanded: 1
blockViewHeight: 400
zoom: 1
scrollViewRect:
serializedVersion: 2
x: -350
y: -350
width: 1131
height: 869
selectedBlocks:
- {fileID: 2121984973}
selectedCommands:
- {fileID: 2121984971}
variables: []
description:
stepPause: 0
colorCommands: 1
hideComponents: 1
saveSelection: 1
localizationId:
showLineNumbers: 0
hideCommands: []
luaEnvironment: {fileID: 0}
luaBindingName: flowchart

2337
Assets/Tests/Narrative/NarrativeTests.unity

File diff suppressed because it is too large Load Diff

9
Assets/Tests/Save.meta

@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 484192c8870014bf888a41f09c360348
folderAsset: yes
timeCreated: 1478534797
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

501
Assets/Tests/Save/LoadFlowchart.unity

@ -0,0 +1,501 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!29 &1
SceneSettings:
m_ObjectHideFlags: 0
m_PVSData:
m_PVSObjectsArray: []
m_PVSPortalsArray: []
m_OcclusionBakeSettings:
smallestOccluder: 5
smallestHole: 0.25
backfaceThreshold: 100
--- !u!104 &2
RenderSettings:
m_ObjectHideFlags: 0
serializedVersion: 7
m_Fog: 0
m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
m_FogMode: 3
m_FogDensity: 0.01
m_LinearFogStart: 0
m_LinearFogEnd: 300
m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1}
m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
m_AmbientIntensity: 1
m_AmbientMode: 3
m_SkyboxMaterial: {fileID: 0}
m_HaloStrength: 0.5
m_FlareStrength: 1
m_FlareFadeSpeed: 3
m_HaloTexture: {fileID: 0}
m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
m_DefaultReflectionMode: 0
m_DefaultReflectionResolution: 128
m_ReflectionBounces: 1
m_ReflectionIntensity: 1
m_CustomReflection: {fileID: 0}
m_Sun: {fileID: 0}
m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1}
--- !u!157 &3
LightmapSettings:
m_ObjectHideFlags: 0
serializedVersion: 7
m_GIWorkflowMode: 1
m_GISettings:
serializedVersion: 2
m_BounceScale: 1
m_IndirectOutputScale: 1
m_AlbedoBoost: 1
m_TemporalCoherenceThreshold: 1
m_EnvironmentLightingMode: 0
m_EnableBakedLightmaps: 0
m_EnableRealtimeLightmaps: 0
m_LightmapEditorSettings:
serializedVersion: 4
m_Resolution: 2
m_BakeResolution: 40
m_TextureWidth: 1024
m_TextureHeight: 1024
m_AO: 0
m_AOMaxDistance: 1
m_CompAOExponent: 1
m_CompAOExponentDirect: 0
m_Padding: 2
m_LightmapParameters: {fileID: 0}
m_LightmapsBakeMode: 1
m_TextureCompression: 1
m_DirectLightInLightProbes: 1
m_FinalGather: 0
m_FinalGatherFiltering: 1
m_FinalGatherRayCount: 256
m_ReflectionCompression: 2
m_LightingDataAsset: {fileID: 0}
m_RuntimeCPUUsage: 25
--- !u!196 &4
NavMeshSettings:
serializedVersion: 2
m_ObjectHideFlags: 0
m_BuildSettings:
serializedVersion: 2
agentRadius: 0.5
agentHeight: 2
agentSlope: 45
agentClimb: 0.4
ledgeDropHeight: 0
maxJumpAcrossDistance: 0
accuratePlacement: 0
minRegionArea: 2
cellSize: 0.16666667
manualCellSize: 0
m_NavMeshData: {fileID: 0}
--- !u!1 &596180617
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
serializedVersion: 4
m_Component:
- 4: {fileID: 596180621}
- 114: {fileID: 596180620}
- 114: {fileID: 596180619}
- 114: {fileID: 596180618}
m_Layer: 0
m_Name: EventSystem
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &596180618
MonoBehaviour:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 596180617}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 1997211142, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
m_Name:
m_EditorClassIdentifier:
m_ForceModuleActive: 0
--- !u!114 &596180619
MonoBehaviour:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 596180617}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 1077351063, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
m_Name:
m_EditorClassIdentifier:
m_HorizontalAxis: Horizontal
m_VerticalAxis: Vertical
m_SubmitButton: Submit
m_CancelButton: Cancel
m_InputActionsPerSecond: 10
m_RepeatDelay: 0.5
m_ForceModuleActive: 0
--- !u!114 &596180620
MonoBehaviour:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 596180617}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: -619905303, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
m_Name:
m_EditorClassIdentifier:
m_FirstSelected: {fileID: 0}
m_sendNavigationEvents: 1
m_DragThreshold: 5
--- !u!4 &596180621
Transform:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 596180617}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 3
--- !u!1 &668327051
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
serializedVersion: 4
m_Component:
- 4: {fileID: 668327056}
- 20: {fileID: 668327055}
- 92: {fileID: 668327054}
- 124: {fileID: 668327053}
- 81: {fileID: 668327052}
m_Layer: 0
m_Name: Main Camera
m_TagString: MainCamera
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!81 &668327052
AudioListener:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 668327051}
m_Enabled: 1
--- !u!124 &668327053
Behaviour:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 668327051}
m_Enabled: 1
--- !u!92 &668327054
Behaviour:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 668327051}
m_Enabled: 1
--- !u!20 &668327055
Camera:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 668327051}
m_Enabled: 1
serializedVersion: 2
m_ClearFlags: 1
m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0}
m_NormalizedViewPortRect:
serializedVersion: 2
x: 0
y: 0
width: 1
height: 1
near clip plane: 0.3
far clip plane: 1000
field of view: 60
orthographic: 1
orthographic size: 5
m_Depth: -1
m_CullingMask:
serializedVersion: 2
m_Bits: 4294967295
m_RenderingPath: -1
m_TargetTexture: {fileID: 0}
m_TargetDisplay: 0
m_TargetEye: 3
m_HDR: 0
m_OcclusionCulling: 1
m_StereoConvergence: 10
m_StereoSeparation: 0.022
m_StereoMirrorMode: 0
--- !u!4 &668327056
Transform:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 668327051}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: -10}
m_LocalScale: {x: 1, y: 1, z: 1}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 0
--- !u!1 &1584700493
GameObject:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
serializedVersion: 4
m_Component:
- 4: {fileID: 1584700495}
- 114: {fileID: 1584700494}
m_Layer: 0
m_Name: _FungusState
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &1584700494
MonoBehaviour:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1584700493}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 61dddfdc5e0e44ca298d8f46f7f5a915, type: 3}
m_Name:
m_EditorClassIdentifier:
selectedFlowchart: {fileID: 1728985435}
--- !u!4 &1584700495
Transform:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1584700493}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 1
--- !u!1 &1728985428
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 142980, guid: 5e7fbc8d4eb714b279eeeef2262c1e1a, type: 2}
m_PrefabInternal: {fileID: 0}
serializedVersion: 4
m_Component:
- 4: {fileID: 1728985436}
- 114: {fileID: 1728985435}
- 114: {fileID: 1728985432}
- 114: {fileID: 1728985431}
- 114: {fileID: 1728985430}
- 114: {fileID: 1728985429}
- 114: {fileID: 1728985438}
- 114: {fileID: 1728985437}
- 114: {fileID: 1728985433}
- 114: {fileID: 1728985434}
m_Layer: 0
m_Name: Flowchart
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &1728985429
MonoBehaviour:
m_ObjectHideFlags: 2
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1728985428}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5d02d9822eec54c98afe95bb497211b3, type: 3}
m_Name:
m_EditorClassIdentifier:
scope: 0
key: BoolVar
value: 1
--- !u!114 &1728985430
MonoBehaviour:
m_ObjectHideFlags: 2
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1728985428}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: afb91b566ceda411bad1e9d3c3243ecc, type: 3}
m_Name:
m_EditorClassIdentifier:
scope: 0
key: IntVar
value: 2
--- !u!114 &1728985431
MonoBehaviour:
m_ObjectHideFlags: 2
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1728985428}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 705fa1ac97df74e3a84ff952ffd923f1, type: 3}
m_Name:
m_EditorClassIdentifier:
scope: 0
key: FloatVar
value: 1
--- !u!114 &1728985432
MonoBehaviour:
m_ObjectHideFlags: 2
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1728985428}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4580f28dd8581476b810b38eea2f1316, type: 3}
m_Name:
m_EditorClassIdentifier:
scope: 0
key: StringVar
value: One
--- !u!114 &1728985433
MonoBehaviour:
m_ObjectHideFlags: 2
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1728985428}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 000864f8e9e1748a39807861d0e60e29, type: 3}
m_Name:
m_EditorClassIdentifier:
parentBlock: {fileID: 1728985437}
keyPressType: 0
keyCode: 108
--- !u!114 &1728985434
MonoBehaviour:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1728985428}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4bd5b7f5cc3944217aa05a6fa8552baf, type: 3}
m_Name:
m_EditorClassIdentifier:
itemId: 5
indentLevel: 0
saveKey:
stringRef: {fileID: 0}
stringVal: savedata
--- !u!114 &1728985435
MonoBehaviour:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 11430050, guid: 5e7fbc8d4eb714b279eeeef2262c1e1a,
type: 2}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1728985428}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 7a334fe2ffb574b3583ff3b18b4792d3, type: 3}
m_Name:
m_EditorClassIdentifier:
version: 1
scrollPos: {x: 1.6562496, y: 1.0743227}
variablesScrollPos: {x: 0, y: 0}
variablesExpanded: 1
blockViewHeight: 400
zoom: 0.98893297
scrollViewRect:
serializedVersion: 2
x: -368.287
y: -369.7274
width: 1216.2789
height: 951.2311
selectedBlocks:
- {fileID: 1728985437}
selectedCommands:
- {fileID: 1728985434}
variables:
- {fileID: 1728985432}
- {fileID: 1728985431}
- {fileID: 1728985430}
- {fileID: 1728985429}
- {fileID: 1728985438}
description:
stepPause: 0
colorCommands: 1
hideComponents: 1
saveSelection: 1
localizationId:
showLineNumbers: 0
hideCommands: []
luaEnvironment: {fileID: 0}
luaBindingName: flowchart
--- !u!4 &1728985436
Transform:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 467082, guid: 5e7fbc8d4eb714b279eeeef2262c1e1a, type: 2}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1728985428}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 2
--- !u!114 &1728985437
MonoBehaviour:
m_ObjectHideFlags: 2
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1728985428}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 3d3d73aef2cfc4f51abf34ac00241f60, type: 3}
m_Name:
m_EditorClassIdentifier:
nodeRect:
serializedVersion: 2
x: 103.50756
y: 73.75383
width: 120
height: 40
tint: {r: 1, g: 1, b: 1, a: 1}
useCustomTint: 0
itemId: 4
blockName: Load
description:
eventHandler: {fileID: 1728985433}
commandList:
- {fileID: 1728985434}
--- !u!114 &1728985438
MonoBehaviour:
m_ObjectHideFlags: 2
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1728985428}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4580f28dd8581476b810b38eea2f1316, type: 3}
m_Name:
m_EditorClassIdentifier:
scope: 0
key: StringVar2
value: Two

8
Assets/Tests/Save/LoadFlowchart.unity.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 69eade49a291342f7a720011281fa97c
timeCreated: 1478534797
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

554
Assets/Tests/Save/SaveFlowchart.unity

@ -0,0 +1,554 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!29 &1
SceneSettings:
m_ObjectHideFlags: 0
m_PVSData:
m_PVSObjectsArray: []
m_PVSPortalsArray: []
m_OcclusionBakeSettings:
smallestOccluder: 5
smallestHole: 0.25
backfaceThreshold: 100
--- !u!104 &2
RenderSettings:
m_ObjectHideFlags: 0
serializedVersion: 7
m_Fog: 0
m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
m_FogMode: 3
m_FogDensity: 0.01
m_LinearFogStart: 0
m_LinearFogEnd: 300
m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1}
m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
m_AmbientIntensity: 1
m_AmbientMode: 3
m_SkyboxMaterial: {fileID: 0}
m_HaloStrength: 0.5
m_FlareStrength: 1
m_FlareFadeSpeed: 3
m_HaloTexture: {fileID: 0}
m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
m_DefaultReflectionMode: 0
m_DefaultReflectionResolution: 128
m_ReflectionBounces: 1
m_ReflectionIntensity: 1
m_CustomReflection: {fileID: 0}
m_Sun: {fileID: 0}
m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1}
--- !u!157 &3
LightmapSettings:
m_ObjectHideFlags: 0
serializedVersion: 7
m_GIWorkflowMode: 1
m_GISettings:
serializedVersion: 2
m_BounceScale: 1
m_IndirectOutputScale: 1
m_AlbedoBoost: 1
m_TemporalCoherenceThreshold: 1
m_EnvironmentLightingMode: 0
m_EnableBakedLightmaps: 0
m_EnableRealtimeLightmaps: 0
m_LightmapEditorSettings:
serializedVersion: 4
m_Resolution: 2
m_BakeResolution: 40
m_TextureWidth: 1024
m_TextureHeight: 1024
m_AO: 0
m_AOMaxDistance: 1
m_CompAOExponent: 1
m_CompAOExponentDirect: 0
m_Padding: 2
m_LightmapParameters: {fileID: 0}
m_LightmapsBakeMode: 1
m_TextureCompression: 1
m_DirectLightInLightProbes: 1
m_FinalGather: 0
m_FinalGatherFiltering: 1
m_FinalGatherRayCount: 256
m_ReflectionCompression: 2
m_LightingDataAsset: {fileID: 0}
m_RuntimeCPUUsage: 25
--- !u!196 &4
NavMeshSettings:
serializedVersion: 2
m_ObjectHideFlags: 0
m_BuildSettings:
serializedVersion: 2
agentRadius: 0.5
agentHeight: 2
agentSlope: 45
agentClimb: 0.4
ledgeDropHeight: 0
maxJumpAcrossDistance: 0
accuratePlacement: 0
minRegionArea: 2
cellSize: 0.16666667
manualCellSize: 0
m_NavMeshData: {fileID: 0}
--- !u!1 &596180617
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
serializedVersion: 4
m_Component:
- 4: {fileID: 596180621}
- 114: {fileID: 596180620}
- 114: {fileID: 596180619}
- 114: {fileID: 596180618}
m_Layer: 0
m_Name: EventSystem
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &596180618
MonoBehaviour:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 596180617}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 1997211142, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
m_Name:
m_EditorClassIdentifier:
m_ForceModuleActive: 0
--- !u!114 &596180619
MonoBehaviour:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 596180617}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 1077351063, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
m_Name:
m_EditorClassIdentifier:
m_HorizontalAxis: Horizontal
m_VerticalAxis: Vertical
m_SubmitButton: Submit
m_CancelButton: Cancel
m_InputActionsPerSecond: 10
m_RepeatDelay: 0.5
m_ForceModuleActive: 0
--- !u!114 &596180620
MonoBehaviour:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 596180617}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: -619905303, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3}
m_Name:
m_EditorClassIdentifier:
m_FirstSelected: {fileID: 0}
m_sendNavigationEvents: 1
m_DragThreshold: 5
--- !u!4 &596180621
Transform:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 596180617}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 3
--- !u!1 &668327051
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
serializedVersion: 4
m_Component:
- 4: {fileID: 668327056}
- 20: {fileID: 668327055}
- 92: {fileID: 668327054}
- 124: {fileID: 668327053}
- 81: {fileID: 668327052}
m_Layer: 0
m_Name: Main Camera
m_TagString: MainCamera
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!81 &668327052
AudioListener:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 668327051}
m_Enabled: 1
--- !u!124 &668327053
Behaviour:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 668327051}
m_Enabled: 1
--- !u!92 &668327054
Behaviour:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 668327051}
m_Enabled: 1
--- !u!20 &668327055
Camera:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 668327051}
m_Enabled: 1
serializedVersion: 2
m_ClearFlags: 1
m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0}
m_NormalizedViewPortRect:
serializedVersion: 2
x: 0
y: 0
width: 1
height: 1
near clip plane: 0.3
far clip plane: 1000
field of view: 60
orthographic: 1
orthographic size: 5
m_Depth: -1
m_CullingMask:
serializedVersion: 2
m_Bits: 4294967295
m_RenderingPath: -1
m_TargetTexture: {fileID: 0}
m_TargetDisplay: 0
m_TargetEye: 3
m_HDR: 0
m_OcclusionCulling: 1
m_StereoConvergence: 10
m_StereoSeparation: 0.022
m_StereoMirrorMode: 0
--- !u!4 &668327056
Transform:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 668327051}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: -10}
m_LocalScale: {x: 1, y: 1, z: 1}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 0
--- !u!1 &1584700493
GameObject:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
serializedVersion: 4
m_Component:
- 4: {fileID: 1584700495}
- 114: {fileID: 1584700494}
m_Layer: 0
m_Name: _FungusState
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &1584700494
MonoBehaviour:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1584700493}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 61dddfdc5e0e44ca298d8f46f7f5a915, type: 3}
m_Name:
m_EditorClassIdentifier:
selectedFlowchart: {fileID: 1728985435}
--- !u!4 &1584700495
Transform:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1584700493}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 1
--- !u!1 &1728985428
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 142980, guid: 5e7fbc8d4eb714b279eeeef2262c1e1a, type: 2}
m_PrefabInternal: {fileID: 0}
serializedVersion: 4
m_Component:
- 4: {fileID: 1728985436}
- 114: {fileID: 1728985435}
- 114: {fileID: 1728985434}
- 114: {fileID: 1728985432}
- 114: {fileID: 1728985431}
- 114: {fileID: 1728985430}
- 114: {fileID: 1728985429}
- 114: {fileID: 1728985438}
- 114: {fileID: 1728985439}
- 114: {fileID: 1728985441}
- 114: {fileID: 1728985440}
- 114: {fileID: 1728985437}
m_Layer: 0
m_Name: Flowchart
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &1728985429
MonoBehaviour:
m_ObjectHideFlags: 2
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1728985428}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 5d02d9822eec54c98afe95bb497211b3, type: 3}
m_Name:
m_EditorClassIdentifier:
scope: 0
key: BoolVar
value: 1
--- !u!114 &1728985430
MonoBehaviour:
m_ObjectHideFlags: 2
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1728985428}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: afb91b566ceda411bad1e9d3c3243ecc, type: 3}
m_Name:
m_EditorClassIdentifier:
scope: 0
key: IntVar
value: 2
--- !u!114 &1728985431
MonoBehaviour:
m_ObjectHideFlags: 2
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1728985428}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 705fa1ac97df74e3a84ff952ffd923f1, type: 3}
m_Name:
m_EditorClassIdentifier:
scope: 0
key: FloatVar
value: 1
--- !u!114 &1728985432
MonoBehaviour:
m_ObjectHideFlags: 2
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1728985428}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4580f28dd8581476b810b38eea2f1316, type: 3}
m_Name:
m_EditorClassIdentifier:
scope: 0
key: StringVar
value: One
--- !u!114 &1728985434
MonoBehaviour:
m_ObjectHideFlags: 2
m_PrefabParentObject: {fileID: 11433304, guid: 5e7fbc8d4eb714b279eeeef2262c1e1a,
type: 2}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1728985428}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 3d3d73aef2cfc4f51abf34ac00241f60, type: 3}
m_Name:
m_EditorClassIdentifier:
nodeRect:
serializedVersion: 2
x: 68
y: 70
width: 120
height: 40
tint: {r: 1, g: 1, b: 1, a: 1}
useCustomTint: 0
itemId: 0
blockName: Save
description:
eventHandler: {fileID: 1728985440}
commandList:
- {fileID: 1728985441}
--- !u!114 &1728985435
MonoBehaviour:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 11430050, guid: 5e7fbc8d4eb714b279eeeef2262c1e1a,
type: 2}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1728985428}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 7a334fe2ffb574b3583ff3b18b4792d3, type: 3}
m_Name:
m_EditorClassIdentifier:
version: 1
scrollPos: {x: 1.6562496, y: 1.0743227}
variablesScrollPos: {x: 0, y: 0}
variablesExpanded: 1
blockViewHeight: 400
zoom: 0.98893297
scrollViewRect:
serializedVersion: 2
x: -351.0967
y: -353.54834
width: 1199.0886
height: 873.3693
selectedBlocks:
- {fileID: 1728985434}
selectedCommands: []
variables:
- {fileID: 1728985432}
- {fileID: 1728985431}
- {fileID: 1728985430}
- {fileID: 1728985429}
- {fileID: 1728985438}
description:
stepPause: 0
colorCommands: 1
hideComponents: 1
saveSelection: 1
localizationId:
showLineNumbers: 0
hideCommands: []
luaEnvironment: {fileID: 0}
luaBindingName: flowchart
--- !u!4 &1728985436
Transform:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 467082, guid: 5e7fbc8d4eb714b279eeeef2262c1e1a, type: 2}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1728985428}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 2
--- !u!114 &1728985437
MonoBehaviour:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1728985428}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: ec422cd568a9c4a31ad7c36d0572b9da, type: 3}
m_Name:
m_EditorClassIdentifier:
itemId: 4
indentLevel: 0
storyText: Resumed ok!
description:
character: {fileID: 0}
portrait: {fileID: 0}
voiceOverClip: {fileID: 0}
showAlways: 1
showCount: 1
extendPrevious: 0
fadeWhenDone: 1
waitForClick: 1
stopVoiceover: 1
setSayDialog: {fileID: 0}
--- !u!114 &1728985438
MonoBehaviour:
m_ObjectHideFlags: 2
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1728985428}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4580f28dd8581476b810b38eea2f1316, type: 3}
m_Name:
m_EditorClassIdentifier:
scope: 0
key: StringVar2
value: Two
--- !u!114 &1728985439
MonoBehaviour:
m_ObjectHideFlags: 2
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1728985428}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 3d3d73aef2cfc4f51abf34ac00241f60, type: 3}
m_Name:
m_EditorClassIdentifier:
nodeRect:
serializedVersion: 2
x: 266.3094
y: 70.72026
width: 120
height: 40
tint: {r: 1, g: 1, b: 1, a: 1}
useCustomTint: 0
itemId: 2
blockName: Resume
description:
eventHandler: {fileID: 0}
commandList:
- {fileID: 1728985437}
--- !u!114 &1728985440
MonoBehaviour:
m_ObjectHideFlags: 2
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1728985428}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 000864f8e9e1748a39807861d0e60e29, type: 3}
m_Name:
m_EditorClassIdentifier:
parentBlock: {fileID: 1728985434}
keyPressType: 0
keyCode: 115
--- !u!114 &1728985441
MonoBehaviour:
m_ObjectHideFlags: 2
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1728985428}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 0b115619cb83b4d6ab8047d0e9407403, type: 3}
m_Name:
m_EditorClassIdentifier:
itemId: 3
indentLevel: 0
saveKey:
stringRef: {fileID: 0}
stringVal: savedata
resumeBlock: {fileID: 1728985439}

8
Assets/Tests/Save/SaveFlowchart.unity.meta

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 809957b90ee744f3dbfaeafc4e8d8525
timeCreated: 1478534797
licenseType: Free
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

1
Docs/Docs.mdproj

@ -301,5 +301,6 @@
<None Include="top_pages\mainpage.md" />
<None Include="fungus_docs\coding_tips.md" />
<None Include="fungus_docs\coding_standard.md" />
<None Include="fungus_docs\save_system.md" />
</ItemGroup>
</Project>

2
Docs/Doxyfile

@ -38,7 +38,7 @@ PROJECT_NAME = Fungus
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = v3.4.0
PROJECT_NUMBER = v3.5.0
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a

13
Docs/command_ref/core_events.md

@ -1,10 +1,6 @@
# Core event handlers # {#core_events}
[TOC]
# Flowchart Enabled # {#FlowchartEnabled}
The block will execute when the Flowchart game object is enabled.
Defined in Fungus.FlowchartEnabled
# Game Started # {#GameStarted}
The block will execute when the game starts playing.
@ -14,12 +10,3 @@ Property | Type | Description
--- | --- | ---
Wait For Frames | System.Int32 | Wait for a number of frames after startup before executing the Block. Can help fix startup order issues.
# Message Received # {#MessageReceived}
The block will execute when the specified message is received from a Send Message command.
Defined in Fungus.MessageReceived
Property | Type | Description
--- | --- | ---
Message | System.String | Fungus message to listen for

16
Docs/command_ref/flow_commands.md

@ -14,6 +14,7 @@ Property | Type | Description
--- | --- | ---
Target Flowchart | Fungus.Flowchart | Flowchart which contains the block to execute. If none is specified then the current Flowchart is used.
Target Block | Fungus.Block | Block to start executing
Start Label | Fungus.StringData | Label to start exeuction at. Takes priority over startIndex.
Start Index | System.Int32 | Command index to start executing
Call Mode | Fungus.CallMode | Select if the calling block should stop or continue executing commands, or wait until the called block finishes.
@ -85,6 +86,21 @@ Loading Image | UnityEngine.Texture2D | Image to display while loading the scene
Quits the application. Does not work in Editor or Webplayer builds. Shouldn't generally be used on iOS.
Defined in Fungus.Quit
# Save Point # {#SavePoint}
Creates a Save Point and adds it to the Save History. The player can save the Save History to peristent storage and load it again later using the Save Menu.
Defined in Fungus.SavePoint
Property | Type | Description
--- | --- | ---
Is Start Point | System.Boolean | Marks this Save Point as the starting point for Flowchart execution in the scene. Each scene in your game should have exactly one Save Point with this enabled.
Key Mode | Fungus.SavePoint+KeyMode | How the Save Point Key for this Save Point is defined.
Custom Key | System.String | A string key which uniquely identifies this save point.
Description Mode | Fungus.SavePoint+DescriptionMode | How the description for this Save Point is defined.
Custom Description | System.String | A short description of this save point.
Fire Event | System.Boolean | Fire a Save Point Loaded event when this command executes.
Resume On Load | System.Boolean | Resume execution from this location after loading this Save Point.
# Send Message # {#SendMessage}
Sends a message to either the owner Flowchart or all Flowcharts in the scene. Blocks can listen for this message using a Message Received event handler.

25
Docs/command_ref/scene_events.md

@ -0,0 +1,25 @@
# Scene event handlers # {#scene_events}
[TOC]
# Flowchart Enabled # {#FlowchartEnabled}
The block will execute when the Flowchart game object is enabled.
Defined in Fungus.FlowchartEnabled
# Message Received # {#MessageReceived}
The block will execute when the specified message is received from a Send Message command.
Defined in Fungus.MessageReceived
Property | Type | Description
--- | --- | ---
Message | System.String | Fungus message to listen for
# Save Point Loaded # {#SavePointLoaded}
Execute this block when a saved point is loaded. Use the 'new_game' key to handle game start.
Defined in Fungus.SavePointLoaded
Property | Type | Description
--- | --- | ---
Save Point Keys | System.Collections.Generic.List`1[System.String] | Block will execute if the Save Key of the loaded save point matches this save key.

1
Docs/command_ref/sprite_events.md

@ -52,4 +52,5 @@ Defined in Fungus.ObjectClicked
Property | Type | Description
--- | --- | ---
Clickable Object | Fungus.Clickable2D | Object that the user can click or tap on
Wait Frames | System.Int32 | Wait for a number of frames before executing the block.

134
Docs/fungus_docs/save_system.md

@ -0,0 +1,134 @@
# Saving and Loading # {#save_system}
[TOC]
# Introduction # {#save_introduction}
**N.B. The Save System is currently in Beta to get feedback from the community. There will probably be breaking changes in future updates as we improve the design.**
The %Fungus Save System provides an easy way to save and load the execution state of Flowcharts in your game.
It works by storing a series of Save Points as the player progresses through the game, to build up a Save History. A basic Save Menu UI is provided to allow the player to Save, Load, Restart, Rewind and Fast Forward through the Save History.
![img save_history]
A Save Point is created by executing a Save Point command in a Flowchart. When a Save Point is loaded back later, execution resumes from immediately after this Save Point command. The save system looks after restoring the state of Flowchart variables at each Save Point and you can also be notified when a particular Save Point has loaded via the Save Point Loaded event handler.
If you are using the old commands for saving individual variables (Set Save Profile, Save Variable, Load Variable), they still work but they’re separate to this new save system.
# The Save Game example scene # {#save_example_scene}
To see how the save system works, open the example scene *FungusExamples/Savegame/SaveGame.unity*
Press play in Unity and click through the short story. The Save Menu can be accessed at any time by clicking the small gears icon in the top right. Try saving, loading, rewinding, fast forwarding and restarting at different points as you play through the story. Also try saving the game in the middle of the story and stopping the game. Press Play again and notice that the game resumes where you left off.
The Save Menu also supports an auto-saving mode where the game is saved to disk at every Save Point. You can enable this by selecting the Save Menu object and selecting the Auto Save property. The Save and Load buttons are disabled when using Auto Save.
The following are the key elements that are used to implement saving in this example scene.
## The Save Menu UI ## {#save_menu_ui}
![img save_menu]
The Save Menu object can be seen In the root of the hierarchy window. This object controls the UI menu that the player uses to interact with the save system. The Save Menu is a singleton object that persists across scene loads, so you only need to add it once in the first scene of your game.
To add a Save Menu to your game, select *Tools > %Fungus > Create > Save Menu*.
## Creating Save Points ## {#save_creating_save_points}
Save Points are created by executing Save Point commands in a Flowchart.
To see this in the example scene, ensure the Flowchart window is displayed (via *Tools > %Fungus > Flowchart Window*), then select the Flowchart object in the hierarchy window and select each of the Blocks in the Flowchart. The first command in each Block is a Save Point command (added via *Flow > Save Point*).
When each Save Point command executes, it adds a new Save Point to the Save History. When you load a previously saved game, execution resumes from immediately after the Save Point command that created that Save Point.
In the example scene, select the ‘Start’ Block in the Flowchart window, and select the Save Point command at the top of the command list. Notice that the Is Start Point property is enabled and that this is the only Save Point command in the Flowchart which has this option enabled. There should only ever be one Start Point in a scene.
When you start a new game, %Fungus looks for a Save Point command with the Is Start Point property enabled and executes it. When loading a previously saved game, %Fungus starts execution at the relevant Save Point command and ignores the start point.
This means that if your game supports saving then you should always have exactly one Save Point command with the Is Start Point property enabled in every scene.
N.B. The Game Started event handler will fire for both new games and loaded games which is generally not what you want, so avoid using it in games that support saving.
## Handling Save Point Loaded events ## {#save_point_loaded_events}
You often need to do some additional work when a saved game loads up to ensure the scene is in the correct state. E.g. The camera might need to be moved to the appropriate location or a certain music track played at this point in the game. An easy way to do this is via the Save Point Loaded event handler.
In the example scene, select the ‘Play Music 1’ Block in the Flowchart, and see it has a Save Point Loaded event handler. This will execute the Block when any of the Save Points in the Save Point Keys list loads. In this case we simply play the correct piece of music for this part of the game, but you could do any setup needed here.
The Save Point Loaded event handler will also fire when a matching Save Point command executes (if the Fire Event property is enabled). This allows you to place all the scene setup commands into a single shared Block which will be called when a Save Point command is first reached or when loading a previously saved game at that Save Point.
## Saving Flowchart variables ## {#save_flowchart_variables}
Each Save Point can store the state of Flowchart variables at that point in time. You use a Save Data object to let the save system know which Flowcharts are to be included in this. Note that only Boolean, Integer, Float and String variables are saved at present.
In the example scene, the Save Data object can be seen in the root of the hierarchy window. The Flowcharts property contains a list of the Flowchart objects to be saved in this scene.
To add a Save Data object to your scene, select *Tools > %Fungus > Create > Save Data*. You can add as many Flowcharts as you like to the list, but make sure that each one has a unique name (e.g. Flowchart1, Flowchart2, etc.) or loading won’t work correctly.
If you are interested in extending the save system to support saving other types of data (besides Flowchart variables), you can either modify or subclass the SaveData component to achieve this.
# The Save Menu # {#save_menu_ui}
The Save Menu is a simple UI which allows players to interact with the %Fungus save system. This section explains what each button does and how to configure the Save Menu properties.
## Save Menu properties ## {#save_menu_properties}
There are 3 main properties that you might want to configure in the Save Menu.
- Load On Start: Automatically load the previously saved game on startup.
- Auto Save: Automatically save the game to disk at every Save Point. When this option is enabled the Save and Load buttons are disabled.
- Restart Deletes Save: Delete the save data from disk when the player restarts the game. This is useful when testing your game to ensure you’re starting from a blank save state.
## Save button ## {#save_save_button}
Pressing the Save button causes the current Save History to be serialized to JSON text and written to persistent storage via the PlayerPrefs class.
## Load button ## {#save_load_button}
Pressing the Load button causes the previously stored JSON data to be deserialized and used to populate the Save History. The most recent Save Point is then used to restore the game state in the following order.
- Load the scene stored in the Save Point (even if it’s the currently loaded scene).
- Restore Flowchart variables to the saved values
- Call Save Point Loaded event handlers and start Flowchart execution after the appropriate Save Point command.
## Rewind and Fast Forward buttons ## {#save_rewind_button}
The Rewind and Fast Forward buttons allow you to move backwards and forwards between Save Points in the Save History.
Each move simply loads the Save Point stored at a particular point in the Save History. This by itself doesn’t change the Save History or write anything to persistent storage. However, if you rewind to an earlier Save Point and start playing again, the next time a Save Point command is executed it will cause all Save Points that are further ahead in time to be discarded permanently.
## Restart button ## {#save_restart_button}
The Restart button clears the Save History and loads the start scene. The start scene is the scene that was active when the Save Menu was first initialized.
# Game Startup # {#save_game_startup}
Remember that the player can choose to load or restart the game at any time. Follow these simple rules to ensure game startup is handled correctly in all cases.
1. Every scene in your game should have exactly one Save Point command with the Is Start Point property enabled. If you have multiple scenes in your game, make sure each one has a start Save Point defined and that it’s the first command executed in the scene.
2. Avoid using the Game Started event handler. This will only work correctly the first time the game is played, not after a saved game is loaded. After loading a saved game, you want execution to start from the Save Point, not at the beginning of your Flowchart again.
3. Use the Save Point Loaded event handler when you want to execute a Block when specific Save Points are loaded. These event handlers are called before execution resumes at the Save Point command, so it gives you a chance to do setup work before gameplay resumes.
# Terminology # {#save_terminology}
## Save Point ## {#save_term_save_point}
A Save Point is a snapshot of the state of the game at a point in time. Each Save Point records the current scene, the current point of Flowchart execution (i.e. at the Save Point command) and the current values of Flowchart variables. Only Boolean, Integer, Float and String variables are saved at present.
## Save Point command ## {#save_term_save_point_command}
The Save Point command is used in a Flowchart to create a Save Point at that point in the execution. Each individual Save Point command should have a unique Save Point Key. The Resume On Load option causes execution to resume from this point after the Save Point is loaded.
## Save Point Key ## {#save_term_save_point_key}
A Save Point Key is a unique string identifier for a single Save Point. By default, the name of the parent Block is used for the Save Point Key, but you can also use a custom key if required (e.g. multiple Save Point commands in a single Block).
N.B. Each key must be unique per scene or loading won’t work correctly!
## Save History ## {#save_term_history}
The Save History contains a list of previously recorded Save Points, stored in chronological order. When a Save Point command is executed, a new Save Point is created and appended to the Save History.
To visualize the Save History at runtime, expand the Save Menu object in the hierarchy, select Save Menu > Panel > Debug View and enable the gameobject. A summary of the Save Points in the Save History will be displayed in a text window.
[img save_menu]: ./save_system/save_menu.png
[img save_history]: ./save_system/save_history.png

BIN
Docs/resources/save_system/save_history.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

BIN
Docs/resources/save_system/save_menu.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

1
Docs/top_pages/mainpage.md

@ -16,6 +16,7 @@ There's a wide range of training material available here, suitable for both begi
* @subpage conversation_system
* @subpage community_tutorials
* @subpage narrative_text_tags
* @subpage save_system
* @subpage coding_tips
* @subpage coding_standard
* @subpage glossary

4
ProjectSettings/EditorBuildSettings.asset

@ -6,6 +6,6 @@ EditorBuildSettings:
serializedVersion: 2
m_Scenes:
- enabled: 1
path: Assets/FungusExamples/Sherlock/TheExperiment.unity
path: Assets/FungusExamples/SaveGame/Menu.unity
- enabled: 1
path: Assets/Tests/Lua/SceneB.unity
path: Assets/FungusExamples/SaveGame/SceneA.unity

3
ProjectSettings/ProjectSettings.asset

@ -29,6 +29,7 @@ PlayerSettings:
m_StackTraceTypes: 010000000100000001000000010000000100000001000000
iosShowActivityIndicatorOnLoading: -1
androidShowActivityIndicatorOnLoading: -1
tizenShowActivityIndicatorOnLoading: -1
iosAppInBackgroundBehavior: 0
displayResolutionDialog: 1
iosAllowHTTPDownload: 1
@ -44,6 +45,7 @@ PlayerSettings:
runInBackground: 0
captureSingleScreen: 0
Override IPod Music: 0
muteOtherAudioSources: 0
Prepare IOS For Recording: 0
submitAnalytics: 1
usePlayerLog: 1
@ -144,6 +146,7 @@ PlayerSettings:
tvOSSmallIconLayers: []
tvOSLargeIconLayers: []
tvOSTopShelfImageLayers: []
tvOSTopShelfImageWideLayers: []
iOSLaunchScreenType: 0
iOSLaunchScreenPortrait: {fileID: 0}
iOSLaunchScreenLandscape: {fileID: 0}

Loading…
Cancel
Save