save / load dans un fichier

problème : le save et le load fonctionnait avec un string en mémoire

solution : créer un fichier save.txt dans les assets quand on sauvegarde, et lire de ce fichier quand on load.
This commit is contained in:
Felix Boucher 2023-05-28 17:37:54 -04:00
parent d4f32e439f
commit f1a328122c
6 changed files with 64 additions and 34 deletions

View File

@ -407,7 +407,7 @@ MonoBehaviour:
_isInvisible: 0 _isInvisible: 0
_isCollidable: 0 _isCollidable: 0
_isTrigger: 0 _isTrigger: 0
_renderOrder: 0 _renderOrder: 1
_renderLayer: Default _renderLayer: Default
- _key: Spawners - _key: Spawners
_tiles: _tiles:

View File

@ -3,6 +3,12 @@ using UnityEngine;
public interface ILevelObject public interface ILevelObject
{ {
public enum ObjectType
{
Tile = 0,
Prefab = 1
}
string Name { get; } string Name { get; }
Vector3 Position { get; } Vector3 Position { get; }
void LevelUpdate(); void LevelUpdate();

View File

@ -5,6 +5,8 @@ using UnityEngine;
using UnityEngine.Tilemaps; using UnityEngine.Tilemaps;
using GatherAndDefend.LevelEditor; using GatherAndDefend.LevelEditor;
using Unity.VisualScripting.YamlDotNet.Core.Tokens; using Unity.VisualScripting.YamlDotNet.Core.Tokens;
using System.Text;
using System.IO;
#region [custom inspector] #region [custom inspector]
#if UNITY_EDITOR #if UNITY_EDITOR
@ -32,6 +34,7 @@ public class LevelManagerEditor : Editor
#region [singleton level manager] #region [singleton level manager]
public class LevelManager : Singleton<LevelManager> public class LevelManager : Singleton<LevelManager>
{ {
string SavePath => Application.dataPath + "/save.txt";
public delegate void LevelAction(ILevelObject levelObject); public delegate void LevelAction(ILevelObject levelObject);
public delegate bool LevelPredicate<T>(T levelObject) where T : ILevelObject; public delegate bool LevelPredicate<T>(T levelObject) where T : ILevelObject;
public event LevelAction Added; public event LevelAction Added;
@ -121,8 +124,6 @@ public class LevelManager : Singleton<LevelManager>
toRemove.Clear(); toRemove.Clear();
} }
private string saved;
public void ClearLevel() public void ClearLevel()
{ {
foreach (var obj in _levelObjects) foreach (var obj in _levelObjects)
@ -131,22 +132,15 @@ public class LevelManager : Singleton<LevelManager>
} }
Clear(); Clear();
} }
public void SaveFile()
{
var list = _levelObjects.Select(obj => obj.ToDictionary()).ToList();
list.Add(new Dictionary<string, object>()
{
{Database.TYPE, "Level" },
{"Name", _currentLevel.name }
});
saved = JsonConvert.SerializeObject(list);
Debug.Log("game saved successfully"); /// <summary>
} /// permet de loader un scriptable object de niveau
/// </summary>
public void LoadLevel(Level level, bool clear = false) /// <param name="level">le niveau à loader</param>
/// <param name="shouldClear">est ce qu'on veut effacer ce qui est déjà là?</param>
public void LoadLevel(Level level, bool shouldClear = false)
{ {
if (clear) if (shouldClear)
{ {
ClearLevel(); ClearLevel();
} }
@ -177,9 +171,15 @@ public class LevelManager : Singleton<LevelManager>
} }
Debug.Log("level loaded successfully"); Debug.Log("level loaded successfully");
} }
public void LoadLevel(string levelName, bool clear = false)
/// <summary>
/// permet de loader un scriptable object de niveau
/// </summary>
/// <param name="levelName">le nom du niveau à loader</param>
/// <param name="shouldClear">est ce qu'on veut effacer ce qui est déjà là?</param>
public void LoadLevel(string levelName, bool shouldClear = false)
{ {
if (clear) if (shouldClear)
{ {
ClearLevel(); ClearLevel();
} }
@ -187,18 +187,31 @@ public class LevelManager : Singleton<LevelManager>
//fetch level from database //fetch level from database
_currentLevel = Database.Instance.ScriptableObjects[levelName] as Level; _currentLevel = Database.Instance.ScriptableObjects[levelName] as Level;
LoadLevel(_currentLevel, clear); LoadLevel(_currentLevel, shouldClear);
} }
public void SaveFile()
{
var list = _levelObjects.Select(obj => obj.ToDictionary()).ToList();
string saved = JsonConvert.SerializeObject(list);
File.WriteAllText(SavePath, saved, Encoding.UTF8);
Debug.Log("game saved successfully");
}
public void LoadFile() public void LoadFile()
{ {
ClearLevel();
string saved = File.ReadAllText(SavePath, Encoding.UTF8);
var dicts = JsonConvert.DeserializeObject<List<Dictionary<string, object>>>(saved); var dicts = JsonConvert.DeserializeObject<List<Dictionary<string, object>>>(saved);
var prefabDicts = dicts.FindAll(x => x[Database.TYPE].ToString() == nameof(Database.Prefabs)); ClearLevel();
var prefabDicts = dicts.FindAll(x => x[nameof(ILevelObject.ObjectType)].ToString() == nameof(ILevelObject.ObjectType.Prefab));
foreach (var prefabDict in prefabDicts) CreatePrefab(prefabDict); foreach (var prefabDict in prefabDicts) CreatePrefab(prefabDict);
var tileDicts = dicts.FindAll(x => x[Database.TYPE].ToString() == nameof(Database.ScriptableObjects)); var tileDicts = dicts.FindAll(x => x[nameof(ILevelObject.ObjectType)].ToString() == nameof(ILevelObject.ObjectType.Tile));
foreach (var tileDict in tileDicts) CreateTile(tileDict); foreach (var tileDict in tileDicts) CreateTile(tileDict);
Debug.Log("game loaded successfully"); Debug.Log("game loaded successfully");
@ -232,11 +245,21 @@ public class LevelManagerScript : MonoBehaviour
void Awake() void Awake()
{ {
if (!_instance) _instance = this; //we don't want to ever have two LevelManagerScript at the same time in the game.
else Destroy(gameObject); //We prevent that by erasing any instances that are not registered as our main instance.
if (!_instance)
{
_instance = this;
}
else
{
Destroy(gameObject);
return;
}
DontDestroyOnLoad(gameObject); DontDestroyOnLoad(gameObject);
LevelManager.Instance.LoadLevel(firstLevel.name, true); if (!firstLevel) throw new System.Exception("there is no first level set in the level manager script");
LevelManager.Instance.LoadLevel(firstLevel, true);
} }
void Update() void Update()
{ {

View File

@ -40,7 +40,7 @@ public abstract class LevelObject : MonoBehaviour, ILevelObject
{ {
{nameof(Name), Name }, {nameof(Name), Name },
{nameof(Position), new float[]{Position.x, Position.y, Position.z } }, {nameof(Position), new float[]{Position.x, Position.y, Position.z } },
{Database.TYPE, nameof(Database.Prefabs) } {nameof(ILevelObject.ObjectType), nameof(ILevelObject.ObjectType.Prefab) }
}; };
} }
public virtual void LoadDictionary(Dictionary<string, object> dict) public virtual void LoadDictionary(Dictionary<string, object> dict)

View File

@ -78,15 +78,16 @@ public abstract class LevelTile : TileBase, ILevelObject
{nameof(Name), Name }, {nameof(Name), Name },
{nameof(Position), new float[]{Position.x, Position.y, Position.z } }, {nameof(Position), new float[]{Position.x, Position.y, Position.z } },
{nameof(Tilemap), Tilemap }, {nameof(Tilemap), Tilemap },
{Database.TYPE, nameof(Database.ScriptableObjects) } {nameof(ILevelObject.ObjectType), nameof(ILevelObject.ObjectType.Tile) }
}; };
} }
public virtual void LoadDictionary(Dictionary<string, object> dict) public virtual void LoadDictionary(Dictionary<string, object> dict)
{ {
Name = dict[nameof(Name)].ToString(); Name = dict[nameof(Name)].ToString();
Position = dict[nameof(Position)].ToVector3(); Position = dict[nameof(Position)].ToVector3();
var tilemapName = dict[nameof(Tilemap)].ToString(); var tilemapName = dict[nameof(Tilemap)].ToString();
_tilemap = FindObjectOfType<Grid>().GetComponentInChildren<Tilemap>(tilemapName); _tilemap = FindObjectOfType<Grid>().GetComponentInChildren<Tilemap>(tilemapName);
} }

View File

@ -29,8 +29,8 @@ public class Opponent : Entity
void AttackEnemy() { void AttackEnemy() {
//Attack Cooldown //Attack Cooldown
if(AttackSpeed < AttackSpeedWait) { if(AttackSpeed < AttackSpeedWait)
{
Enemy.Hp-=AttackDamage; Enemy.Hp-=AttackDamage;
Debug.Log("Ally Hp = " + Enemy.Hp); Debug.Log("Ally Hp = " + Enemy.Hp);