Skip to content
Snippets Groups Projects
Commit 94aee56e authored by Lindinger Erik's avatar Lindinger Erik
Browse files

Merge branch 'save-system' into 'main'

Save and Load system added

See merge request lg100/akai!14
parents ca53ec64 35e7365a
No related branches found
Tags v0.1.3
No related merge requests found
Showing
with 21059 additions and 5 deletions
This diff is collapsed.
fileFormatVersion: 2
guid: e658595cf158f4274b5808696340c9df
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 713bb23451152428c94bed0b10bf2163
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class GameData
{
public int score;
// the value defined in this constructor will be the default values
// the game starts with when there's no data to load
public GameData()
{
this.score = 0;
}
}
fileFormatVersion: 2
guid: 5f64da67d3f0b4c119f12c5e8b648814
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
public class DataPersistenceManager : MonoBehaviour
{
[Header("File Storage Config")]
[SerializeField] private string fileName;
private GameData gameData;
private List<IDataPersistence> dataPersistenceObjects;
private FileDataHandler dataHandler;
public static DataPersistenceManager instance { get; private set; } // able to get the instance publicly, but only be able to modify the instance privately
private void Awake()
{
if (instance != null)
{
Debug.LogError("Found more than one Data Persistence Manager in the scene.");
}
instance = this;
}
private void Start()
{
this.dataHandler = new FileDataHandler(Application.persistentDataPath, fileName); // Will give the operating system standard directory for persisting data in a unity project
this.dataPersistenceObjects = FindAllDataPersistenceObjects();
LoadGame(); // Game is loaded on startup
}
public void NewGame()
{
this.gameData = new GameData(); //create a new game
}
public void LoadGame()
{
// load any saved data from a file using the data handler
this.gameData = dataHandler.Load();
// if no data can be loaded, initialize to a new game
if (this.gameData == null)
{
Debug.Log("No data was found. Initializing data to defaults.");
NewGame();
}
// push the loaded data to all other scripts that need it
foreach (IDataPersistence dataPersistenceObj in dataPersistenceObjects)
{
dataPersistenceObj.LoadData(gameData);
}
Debug.Log("Loaded score count = " + gameData.score);
}
public void SaveGame()
{
// pass the data to other scripts so they can update it
foreach (IDataPersistence dataPersistenceObj in dataPersistenceObjects)
{
dataPersistenceObj.SaveData(ref gameData);
}
Debug.Log("Saved score count = " + gameData.score);
// save the data to file using the data handler
dataHandler.Save(gameData);
}
private void OnApplicationQuit()
{
SaveGame(); // Game will be saved when the Game gets closed
}
private List<IDataPersistence> FindAllDataPersistenceObjects()
{
IEnumerable<IDataPersistence> dataPersistenceObjects = FindObjectsOfType<MonoBehaviour>().OfType<IDataPersistence>(); //Finds all scripts that implemented the data persistence interface in our scene. Those scripts need to extend from MonoBehaviour to be found in this way
return new List<IDataPersistence>(dataPersistenceObjects);
}
}
fileFormatVersion: 2
guid: 76a12b2ce14884d9d8b851b3e44bb359
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.IO;
public class FileDataHandler
{
private string dataDirPath = "";
private string dataFileName = "";
public FileDataHandler(string dataDirPath, string dataFileName)
{
this.dataDirPath = dataDirPath;
this.dataFileName = dataFileName;
}
public GameData Load()
{
// use Path.Combine to account for diffrent OS's having different path seperators
string fullPath = Path.Combine(dataDirPath, dataFileName);
GameData loadedData = null;
if (File.Exists(fullPath))
{
try
{
// load the serialized data from the file
string dataToLoad = "";
// we use using() blocks as they ensure that the connection to that file is closed once we're done reading or writing to it
using (FileStream stream = new FileStream(fullPath, FileMode.Open))
{
using (StreamReader reader = new StreamReader(stream))
{
dataToLoad = reader.ReadToEnd();
}
}
// deserialize the data from Json back into the C# object
loadedData = JsonUtility.FromJson<GameData>(dataToLoad);
}
catch (Exception e)
{
Debug.LogError("Error occured when trying to load data from file: " + fullPath + "\n" + e);
}
}
return loadedData;
}
public void Save(GameData data)
{
// use Path.Combine to account for diffrent OS's having different path seperators
string fullPath = Path.Combine(dataDirPath, dataFileName);
try
{
// create the directory the file will be written to if it doesn't already exist
Directory.CreateDirectory(Path.GetDirectoryName(fullPath));
// serialize the C# game data object into Json
string dataToStore = JsonUtility.ToJson(data, true); // the second parameter true is optional, it let's us format the Json
// write the serialized data to the file
// we use using() blocks as they ensure that the connection to that file is closed once we're done reading or writing to it
using (FileStream stream = new FileStream(fullPath, FileMode.Create))
{
using (StreamWriter writer = new StreamWriter(stream))
{
writer.Write(dataToStore);
}
}
}
catch (Exception e)
{
Debug.LogError("Error occured when trying to save data to file: " + fullPath + "\n" + e);
}
}
}
fileFormatVersion: 2
guid: 1a071c7a33cc2455e8d141aec44b8d28
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
......@@ -4,11 +4,11 @@ using UnityEngine;
using UnityEngine.SceneManagement;
using TMPro;
public class GameSession : MonoBehaviour
public class GameSession : MonoBehaviour, IDataPersistence
{
[SerializeField] int playerLives = 3;
[SerializeField] int score = 0;
[SerializeField] private int playerLives = 3;
[SerializeField] private int score = 0;
[SerializeField] TextMeshProUGUI livesCounter;
[SerializeField] TextMeshProUGUI scoreText;
......@@ -27,6 +27,16 @@ public class GameSession : MonoBehaviour
}
public void LoadData(GameData data)
{
this.score = data.score;
}
public void SaveData(ref GameData data)
{
data.score = this.score;
}
void Start()
{
livesCounter.text = playerLives.ToString();
......@@ -51,9 +61,9 @@ public class GameSession : MonoBehaviour
public void AddToScore(int pointsToAdd)
{
score += pointsToAdd;
scoreText.text = score.ToString();
}
void TakeLife()
......@@ -64,6 +74,11 @@ public class GameSession : MonoBehaviour
livesCounter.text = playerLives.ToString();
}
private void Update()
{
scoreText.text = score.ToString();
}
/*void GoToLastCheckpoint()
{
......
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public interface IDataPersistence
{
void LoadData(GameData data); // the implementing script only cares about reading the data
void SaveData(ref GameData data); // we pass the reference here so that when we save data, we allow the implementing script to modify the data
}
fileFormatVersion: 2
guid: 75e6e21ee4b1742b1a828eb8df31fc3c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Info : MonoBehaviour
{
void Start()
{
Debug.Log(Application.persistentDataPath);
}
}
fileFormatVersion: 2
guid: 626e8f3dd85c84c7ea7aac498c2f8b76
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment