Browse Source

SavePoint now handles starting Flowchart execution for 'normal' scene loads. Use a Save Point with key 'Start' for the first Block to be executed in every scene.

master
Christopher 8 years ago
parent
commit
a3ebe0e75e
  1. 24
      Assets/Fungus/Scripts/Commands/SavePoint.cs
  2. 50
      Assets/Fungus/Scripts/Components/SaveManager.cs
  3. 86
      Assets/Fungus/Scripts/Components/SaveMenu.cs
  4. 15
      Assets/Fungus/Scripts/Signals/SaveManagerSignals.cs
  5. 11
      Assets/Fungus/Scripts/Utils/FungusConstants.cs
  6. 3
      Assets/Fungus/Scripts/Utils/SavePointData.cs
  7. 68
      Assets/FungusExamples/SaveGame/SaveExample.unity

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

@ -2,6 +2,7 @@
// 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
{
@ -10,18 +11,31 @@ namespace Fungus
"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.")]
public class SavePoint : Command
{
[Tooltip("A string key which uniquely identifies this save point. If empty then the parent Block's name will be used.")]
[Tooltip("A string key which uniquely identifies this save point. If you leave this empty then the parent Block's name will be used.")]
[SerializeField] protected string savePointKey = "";
[Tooltip("A short description of this save point. If empty then the current time and date will be used.")]
[Tooltip("A short description of this save point. If you leave this empty then the current time and date will be used.")]
[SerializeField] protected string savePointDescription;
[Tooltip("Fire an event that will be handled by any Save Point Loaded event handler with matching key.")]
[Tooltip("Fire a Save Point Loaded event when this command executes.")]
[SerializeField] protected bool fireEvent = true;
[Tooltip("Resume execution from this command after loading a save point.")]
[Tooltip("Resume execution from here after loading this Save Point.")]
[SerializeField] protected bool resumeFromHere = true;
protected virtual void Start()
{
// Each scene should have one Save Point with the 'Start' key.
// 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).
// If on the other hand, the scene was loaded by loading a Save Point then the Save Manager handles resuming execution at the appropriate point, so we don't need to do anything here.
if (string.Compare(SavePointKey, "Start", true) == 0 &&
!FungusManager.Instance.SaveManager.HasLoadedSavePoint)
{
GetFlowchart().ExecuteBlock(ParentBlock, CommandIndex);
}
}
#region Public members
/// <summary>
@ -69,7 +83,7 @@ namespace Fungus
if (fireEvent)
{
SavePointLoaded.NotifyEventHandlers(savePointKey);
SavePointLoaded.NotifyEventHandlers(SavePointKey);
}
Continue();

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

@ -1,4 +1,5 @@
using UnityEngine;
using System.Collections;
namespace Fungus
{
@ -38,8 +39,37 @@ namespace Fungus
return false;
}
protected virtual void OnEnable()
{
SaveManagerSignals.OnSavePointLoaded += OnSavePointLoaded;
}
protected virtual void OnDisable()
{
SaveManagerSignals.OnSavePointLoaded -= OnSavePointLoaded;
}
protected virtual void OnSavePointLoaded(string savePointKey)
{
// Flag that a save point was loaded.
// The flag remains set for 1 frame to give other components enough time to poll it in their Start method.
HasLoadedSavePoint = true;
StartCoroutine(ResetHasLoadedSavePoint());
}
protected virtual IEnumerator ResetHasLoadedSavePoint()
{
yield return new WaitForEndOfFrame();
HasLoadedSavePoint = false;
}
#region Public members
/// <summary>
/// The default key used for storing save game data in PlayerPrefs.
/// </summary>
public const string DefaultSaveDataKey = "save_data";
/// <summary>
/// Returns the number of Save Points in the Save History.
/// </summary>
@ -50,34 +80,32 @@ namespace Fungus
/// </summary>
public virtual int NumRewoundSavePoints { get { return saveHistory.NumRewoundSavePoints; } }
public virtual bool HasLoadedSavePoint { get; private set; }
/// <summary>
/// Writes the Save History to persistent storage.
/// </summary>
public virtual void Save(string saveDataKey)
public virtual void Save(string saveDataKey = DefaultSaveDataKey)
{
WriteSaveHistory(saveDataKey);
SaveManagerSignals.DoGameSaved(saveDataKey);
}
/// <summary>
/// Loads the Save History from persistent storage.
/// </summary>
public void Load(string saveDataKey)
public void Load(string saveDataKey = DefaultSaveDataKey)
{
if (ReadSaveHistory(saveDataKey))
{
saveHistory.ClearRewoundSavePoints();
saveHistory.LoadLatestSavePoint();
SaveManagerSignals.DoGameLoaded(saveDataKey);
}
}
/// <summary>
/// Deletes a previously stored Save History from persistent storage.
/// </summary>
public void Delete(string saveDataKey)
public void Delete(string saveDataKey = DefaultSaveDataKey)
{
PlayerPrefs.DeleteKey(saveDataKey);
PlayerPrefs.Save();
@ -86,7 +114,7 @@ namespace Fungus
/// <summary>
/// Returns true if save data has previously been stored using this key.
/// </summary>
public bool SaveDataExists(string saveDataKey)
public bool SaveDataExists(string saveDataKey = DefaultSaveDataKey)
{
return PlayerPrefs.HasKey(saveDataKey);
}
@ -108,7 +136,7 @@ namespace Fungus
{
if (saveHistory.NumSavePoints > 0)
{
// Can't rewind the first save point (new_game)
// Rewinding the first save point is not permitted
if (saveHistory.NumSavePoints > 1)
{
saveHistory.Rewind();
@ -142,8 +170,8 @@ namespace Fungus
/// 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 following command.
/// 3. Any label in any block with name matching the key. Execution starts at following command.
/// 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>
public static void ExecuteBlocks(string savePointKey)
{

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

@ -10,12 +10,8 @@ namespace Fungus
/// </summary>
public class SaveMenu : MonoBehaviour
{
const string SaveDataKey = "save_data";
const string NewGameSavePointKey = "new_game";
[Tooltip("On scene start, execute any Save Point Loaded event handlers which have the 'new_game' key")]
[SerializeField] protected bool autoStartGame = true;
[Tooltip("Automatically load the most recently saved game on startup")]
[SerializeField] protected bool loadOnStart = true;
[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;
@ -72,32 +68,19 @@ namespace Fungus
// Assume that the first scene that contains the SaveMenu is also the scene to load on restart.
startScene = SceneManager.GetActiveScene().name;
if (!saveMenuActive)
{
saveMenuGroup.alpha = 0f;
}
if (loadOnStart)
{
var saveManager = FungusManager.Instance.SaveManager;
if (autoStartGame &&
saveManager.NumSavePoints == 0)
if (saveManager.SaveDataExists())
{
StartNewGame();
saveManager.Load();
}
CheckSavePointKeys();
}
protected virtual void StartNewGame()
{
var saveManager = FungusManager.Instance.SaveManager;
// Create an initial save point
saveManager.AddSavePoint(NewGameSavePointKey, "");
// Start game execution
SaveManager.ExecuteBlocks(NewGameSavePointKey);
}
protected virtual void Update()
@ -112,7 +95,7 @@ namespace Fungus
}
if (loadButton != null)
{
loadButton.interactable = saveManager.SaveDataExists(SaveDataKey);
loadButton.interactable = saveManager.SaveDataExists();
}
if (rewindButton != null)
{
@ -124,33 +107,6 @@ namespace Fungus
}
}
/// <summary>
/// Warns if duplicate SavePointKeys are found.
/// </summary>
protected void CheckSavePointKeys()
{
List<string> keys = new List<string>();
var savePoints = GameObject.FindObjectsOfType<SavePoint>();
foreach (var savePoint in savePoints)
{
if (string.IsNullOrEmpty(savePoint.SavePointKey))
{
continue;
}
if (keys.Contains(savePoint.SavePointKey))
{
Debug.LogError("Save Point Key " + savePoint.SavePointKey + " is defined multiple times.");
}
else
{
keys.Add(savePoint.SavePointKey);
}
}
}
protected void PlayClickSound()
{
if (clickAudioSource != null)
@ -159,21 +115,6 @@ namespace Fungus
}
}
/// <summary>
/// Callback for the restart scene load
/// </summary>
protected void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
if (scene.name != startScene)
{
return;
}
SceneManager.sceneLoaded -= OnSceneLoaded;
StartNewGame();
}
#region Public methods
/// <summary>
@ -220,7 +161,7 @@ namespace Fungus
if (saveManager.NumSavePoints > 0)
{
PlayClickSound();
saveManager.Save(SaveDataKey);
saveManager.Save();
}
}
@ -231,10 +172,10 @@ namespace Fungus
{
var saveManager = FungusManager.Instance.SaveManager;
if (saveManager.SaveDataExists(SaveDataKey))
if (saveManager.SaveDataExists())
{
PlayClickSound();
saveManager.Load(SaveDataKey);
saveManager.Load();
}
}
@ -277,17 +218,16 @@ namespace Fungus
return;
}
var saveManager = FungusManager.Instance.SaveManager;
PlayClickSound();
// Reset the Save History for a new game
var saveManager = FungusManager.Instance.SaveManager;
saveManager.ClearHistory();
if (restartDeletesSave)
{
saveManager.Delete(SaveDataKey);
saveManager.Delete();
}
SceneManager.sceneLoaded += OnSceneLoaded;
SceneManager.LoadScene(startScene);
}

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

@ -12,18 +12,11 @@ namespace Fungus
#region Public members
/// <summary>
/// GameSaved signal. Sent just after the game is saved.
/// SavePointLoaded signal. Sent just after a SavePoint is loaded.
/// </summary>
public static event GameSavedHandler OnGameSaved;
public delegate void GameSavedHandler(string saveDataKey);
public static void DoGameSaved(string saveDataKey) { if (OnGameSaved != null) OnGameSaved(saveDataKey); }
/// <summary>
/// GameLoaded signal. Sent just after the game is loaded.
/// </summary>
public static event GameLoadedHandler OnGameLoaded;
public delegate void GameLoadedHandler(string saveDataKey);
public static void DoGameLoaded(string saveDataKey) { if (OnGameLoaded != null) OnGameLoaded(saveDataKey); }
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).

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

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

@ -1,6 +1,7 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using System.Collections;
namespace Fungus
{
@ -34,6 +35,8 @@ namespace Fungus
}
SaveManager.ExecuteBlocks(savePointData.savePointKey);
SaveManagerSignals.DoSavePointLoaded(savePointData.savePointKey);
}
protected static SavePointData Create(string _savePointKey, string _savePointDescription, string _sceneName)

68
Assets/FungusExamples/SaveGame/SaveExample.unity

@ -1287,12 +1287,12 @@ GameObject:
- component: {fileID: 1889213511}
- component: {fileID: 1889213509}
- component: {fileID: 1889213470}
- component: {fileID: 1889213471}
- component: {fileID: 1889213473}
- component: {fileID: 1889213481}
- component: {fileID: 1889213480}
- component: {fileID: 1889213479}
- component: {fileID: 1889213478}
- component: {fileID: 1889213475}
- component: {fileID: 1889213471}
m_Layer: 0
m_Name: Flowchart
m_TagString: Untagged
@ -1302,7 +1302,7 @@ GameObject:
m_IsActive: 1
--- !u!114 &1889213470
MonoBehaviour:
m_ObjectHideFlags: 0
m_ObjectHideFlags: 2
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1889213469}
@ -1322,7 +1322,7 @@ MonoBehaviour:
itemId: 52
blockName: Play Music 1
description:
eventHandler: {fileID: 1889213471}
eventHandler: {fileID: 1889213475}
commandList:
- {fileID: 1889213473}
--- !u!114 &1889213471
@ -1336,13 +1336,14 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 9ca33a026786245d4b10323b87e84d5f, type: 3}
m_Name:
m_EditorClassIdentifier:
parentBlock: {fileID: 1889213470}
parentBlock: {fileID: 1889213481}
savePointKeys:
- new_game
- Queens Chamber
- Use Umbrella
- Duck Down
- The Queen
--- !u!114 &1889213473
MonoBehaviour:
m_ObjectHideFlags: 0
m_ObjectHideFlags: 2
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1889213469}
@ -1394,9 +1395,10 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 9ca33a026786245d4b10323b87e84d5f, type: 3}
m_Name:
m_EditorClassIdentifier:
parentBlock: {fileID: 1889213482}
parentBlock: {fileID: 1889213470}
savePointKeys:
- new_game
- Start
- Queens Chamber
--- !u!114 &1889213476
MonoBehaviour:
m_ObjectHideFlags: 0
@ -1410,7 +1412,7 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
version: 1
scrollPos: {x: -57.30224, y: -63.688995}
scrollPos: {x: -103.9434, y: -49.980755}
variablesScrollPos: {x: 0, y: 0}
variablesExpanded: 1
blockViewHeight: 400
@ -1422,7 +1424,7 @@ MonoBehaviour:
width: 1502.7736
height: 1138.5048
selectedBlocks:
- {fileID: 1889213481}
- {fileID: 1889213500}
selectedCommands: []
variables:
- {fileID: 1889213489}
@ -1450,25 +1452,26 @@ Transform:
m_Father: {fileID: 0}
m_RootOrder: 7
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &1889213479
--- !u!114 &1889213478
MonoBehaviour:
m_ObjectHideFlags: 0
m_ObjectHideFlags: 2
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1889213469}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 9ca33a026786245d4b10323b87e84d5f, type: 3}
m_Script: {fileID: 11500000, guid: 0b115619cb83b4d6ab8047d0e9407403, type: 3}
m_Name:
m_EditorClassIdentifier:
parentBlock: {fileID: 1889213481}
savePointKeys:
- Use Umbrella
- Duck Down
- The Queen
itemId: 61
indentLevel: 0
savePointKey:
savePointDescription:
fireEvent: 1
resumeFromHere: 1
--- !u!114 &1889213480
MonoBehaviour:
m_ObjectHideFlags: 0
m_ObjectHideFlags: 2
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1889213469}
@ -1485,7 +1488,7 @@ MonoBehaviour:
fadeDuration: 1
--- !u!114 &1889213481
MonoBehaviour:
m_ObjectHideFlags: 0
m_ObjectHideFlags: 2
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1889213469}
@ -1496,8 +1499,8 @@ MonoBehaviour:
m_EditorClassIdentifier:
nodeRect:
serializedVersion: 2
x: 81.28943
y: 288.5421
x: 78.28943
y: 294.5421
width: 120
height: 40
tint: {r: 1, g: 1, b: 1, a: 1}
@ -1505,7 +1508,7 @@ MonoBehaviour:
itemId: 59
blockName: Play Music 2
description:
eventHandler: {fileID: 1889213479}
eventHandler: {fileID: 1889213471}
commandList:
- {fileID: 1889213480}
--- !u!114 &1889213482
@ -1528,10 +1531,11 @@ MonoBehaviour:
tint: {r: 1, g: 1, b: 1, a: 1}
useCustomTint: 0
itemId: 16
blockName: new_game
blockName: Start
description:
eventHandler: {fileID: 1889213475}
eventHandler: {fileID: 0}
commandList:
- {fileID: 1889213478}
- {fileID: 1889213474}
- {fileID: 1889213507}
- {fileID: 1889213504}
@ -1632,8 +1636,6 @@ MonoBehaviour:
indentLevel: 0
savePointKey:
savePointDescription:
stringRef: {fileID: 0}
stringVal:
fireEvent: 1
resumeFromHere: 1
--- !u!114 &1889213488
@ -1923,7 +1925,7 @@ MonoBehaviour:
nodeRect:
serializedVersion: 2
x: 542.1676
y: 144.44673
y: 143.44673
width: 120
height: 40
tint: {r: 1, g: 1, b: 1, a: 1}
@ -1954,8 +1956,6 @@ MonoBehaviour:
indentLevel: 0
savePointKey:
savePointDescription:
stringRef: {fileID: 0}
stringVal:
fireEvent: 1
resumeFromHere: 1
--- !u!114 &1889213502
@ -1973,8 +1973,6 @@ MonoBehaviour:
indentLevel: 0
savePointKey:
savePointDescription:
stringRef: {fileID: 0}
stringVal:
fireEvent: 1
resumeFromHere: 1
--- !u!114 &1889213503
@ -2240,8 +2238,6 @@ MonoBehaviour:
indentLevel: 0
savePointKey:
savePointDescription:
stringRef: {fileID: 0}
stringVal:
fireEvent: 1
resumeFromHere: 1
--- !u!1 &2025975869

Loading…
Cancel
Save