a bit long but everything is connected.
I have a script type editor that with right mouse click I can add to a gameobject a script that add to the selected gameobject/s a special id:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
public class GenerateAutomaticGuid : Editor
{
[MenuItem("GameObject/Generate Guid", false, 11)]
private static void GenerateGuid()
{
foreach (GameObject o in Selection.gameObjects)
{
var g = o.GetComponent<GenerateGuid>();
if (!g)
{
g = o.AddComponent<GenerateGuid>();
g.GenerateGuidNum();
}
}
}
}
The GenerateGuidNum method:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GenerateGuid : MonoBehaviour
{
public string uniqueGuidID;
private Guid guidID;
public void GenerateGuidNum()
{
guidID = Guid.NewGuid();
uniqueGuidID = guidID.ToString();
}
}
For example, a gameobject with id:
when I'm saving the game it's creating a text save game and store information including the gameobjects id:
This is part of the saved game text file content:
{"saveObjects":[{"componentsState":[],"gameObjectUniqueID":"b7fbc192-0312-4822-b62d-4a35a212f639","transformSaver":{"position":{"x":-17.84672737121582,"y":1.129213809967
the problem is if someone even me that use this save system delete the object with the unique id or only removed the GenerateGuid script with the unique id from the object.
then when loading the saved game file, it can't find the unique id. the unique id is stored in the text file but not exist in the hierarchy on any object.
how should I handle that case?
example of error:
KeyNotFoundException: The given key 'd9687717-cef7-4e6c-8318-20bcc51e0110' was not present in the dictionary.
System.Collections.Generic.Dictionary`2[TKey,TValue].get_Item (TKey key) (at <1f66344f2f89470293d8b67d71308c07>:0)
SaveLoad.Load (System.String fileName) (at Assets/My Scripts/Save System Scripts/SaveLoad.cs:130)
and this is the SaveLoad script line 130:
zz[keyvalue.Key].SetState(keyvalue.Value);
and the full script:
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class SaveLoad : MonoBehaviour
{
public FadeInOutSaveGameText fadeInOutSaveGame;
public float timeToStartSaving;
public float savingFadeInOutTime;
public int resWidth = 1920;
public int resHeight = 1080;
[Tooltip("If true will save manualy only by the left control key.")]
public bool saveManual = false;
private List<GameObject> objectsToSave;
private string saveString;
private void Awake()
{
if (objectsToSave == null)
{
objectsToSave = new List<GameObject>();
}
var objectsWithGenerateGuid = GameObject.FindObjectsOfType<GenerateGuid>().ToList();
if (objectsWithGenerateGuid.Count > 0 && objectsToSave.Count == 0)
{
for (int i = 0; i < objectsWithGenerateGuid.Count; i++)
{
objectsToSave.Add(objectsWithGenerateGuid[i].gameObject);
}
}
Debug.Log("Start");
for (int i = 0; i < objectsToSave.Count; i++)
{
Debug.Log($"{i}");
Debug.Log($"{objectsToSave[i].name}");
}
Debug.Log("End Init");
}
public void Save()
{
SaveGame saveGame = new SaveGame();
saveGame.saveObjects = new List<SaveObject>();
for (int i = 0; i < objectsToSave.Count; i++)
{
SaveObject saveObject = new SaveObject();
saveObject.transformSaver = new TransformSaver();
Debug.Log($"{i}");
Debug.Log($"{objectsToSave[i].name}");
saveObject.gameObjectUniqueID = objectsToSave[i].GetComponent<GenerateGuid>().uniqueGuidID;
var x = objectsToSave[i].GetComponents<Component>();
var stateQueryComponent = x.Where(component => component is IStateQuery).ToList();
List<KeyToValue> componentsState = new List<KeyToValue>();
foreach (var z in stateQueryComponent)
{
var w = z as IStateQuery;
componentsState.Add(new KeyToValue(w.UniqueId.ToString(), w.GetState()));
}
saveObject.transformSaver.position = objectsToSave[i].transform.position;
saveObject.transformSaver.rotation = objectsToSave[i].transform.rotation;
saveObject.transformSaver.scaling = objectsToSave[i].transform.localScale;
saveObject.componentsState = componentsState;
saveGame.saveObjects.Add(saveObject);
}
string json = JsonUtility.ToJson(saveGame);
SaveSystem.Save(json, resWidth, resHeight);
}
public void Load(string fileName)
{
if (objectsToSave.Count > 0)
{
// Why objectsToSave here is empty ?
Dictionary<string, GameObject> uniqueIdToObject = objectsToSave
.ToDictionary(o => o.GetComponent<GenerateGuid>().uniqueGuidID, o => o);
saveString = SaveSystem.Load(fileName);
if (saveString != null)
{
SaveGame saveGame = JsonUtility.FromJson<SaveGame>(saveString);
if (saveGame != null)
{
foreach (var saveObject in saveGame.saveObjects)
{
List<KeyToValue> loadedComponents = saveObject.componentsState;
var objectToSetState = uniqueIdToObject[saveObject.gameObjectUniqueID];
objectToSetState.transform.position = saveObject.transformSaver.position;
objectToSetState.transform.rotation = saveObject.transformSaver.rotation;
objectToSetState.transform.localScale = saveObject.transformSaver.scaling;
var y = objectToSetState.GetComponents<Component>();
var z = y.Where(component => component is IStateQuery).ToList();
Dictionary<string, IStateQuery> zz = z.ToDictionary(sq => (sq as IStateQuery).UniqueId.ToString(), sq => sq as IStateQuery);
foreach (KeyToValue keyvalue in loadedComponents)
{
zz[keyvalue.Key].SetState(keyvalue.Value);
}
}
}
}
}
}
public IEnumerator SaveWithTime()
{
yield return new WaitForSeconds(timeToStartSaving);
if (objectsToSave.Count == 0)
{
Debug.Log("No objects selected for saving.");
}
if (saveManual == false && objectsToSave.Count > 0)
{
Save();
StartCoroutine(fadeInOutSaveGame.OverAllTime(savingFadeInOutTime));
}
}
public IEnumerator SaveWithTimeManual()
{
yield return new WaitForSeconds(timeToStartSaving);
if (objectsToSave.Count == 0)
{
Debug.Log("No objects selected for saving.");
}
if (saveManual && objectsToSave.Count > 0)
{
Save();
StartCoroutine(fadeInOutSaveGame.OverAllTime(savingFadeInOutTime));
}
}
}