We are using ES3 with a custom script that allows any script to add an 'ISaveLoadComponent' within the hierarchy of a 'SaveLoadEntity'. This had been working great before, but now while it saves everything, the 'LoadInto' code is called but does nothing and throws no error. Other data, such as the 'SiteOres', are loaded correctly, but while eadh 'SaveLoadEntity' gets instantiated, none of the variables within the 'ISaveLoadComponent's are changed (public or with the [ES3Serializable] tag). I have been debugging this for hours now, with no progress.
I'll cut down the code to just the relevant bits, the whole code is provided at the very end.
Here is the save code (works just fine)
Code: Select all
List<SaveLoadEntity> entities = m_Site.SaveLoadEntities;
ES3.Save("SiteEntityCount", entities.Count, settings);
for (int j = 0; j < entities.Count; j++)
{
SaveLoadEntity sle = entities[j];
ES3.Save("SaveLoadEntity_" + j + "ID", sle.UniqueID, settings);
for (int k = 0; k < sle.Components.Length; k++)
{
for (int l = 0; l < sle.Components.Length; l++)
{
if (k != l && sle.Components[k].SLC_UniqueName == sle.Components[l].SLC_UniqueName)
{
GameObject tracePoint = sle.Components[k].SavedComponent.gameObject;
Debug.LogError("Saving component with non-unique uniqueID : " + sle.gameObject.name + " : " + sle.UniqueID + " : " + sle.Components[k].SLC_UniqueName + " : " + DebugHelper.HierarchyTrace(tracePoint));
break;
}
}
if (sle.Components[k] == null) { Debug.LogError("Tried saving a null reference : " + sle.gameObject.name + " : " + sle.UniqueID); break; }
ES3.Save("Component_" + j + "_" + sle.Components[k].SLC_UniqueName, sle.Components[k].SavedComponent, settings);
}
}
Code: Select all
"Component_0_GridOccupant" : {
"__type" : "GridOccupant,SiteCore",
"value" : {
"_ES3Ref" : "3797481660449551490",
"goID" : "1084078376051653123",
"_IsRooted_Offline" : true,
"IsRooted" : true,
"GridIndex" : 3,
"LocalPose" : {
"Point" : {
"m_P" : -10,
"m_Q" : -6
},
"Height" : -0.3107605,
"Rotation" : 0
}
}
},
And here is the equivalent load section (does not load any data into the components)
Code: Select all
int entitiesCount = ES3.Load<int>("SiteEntityCount", settings);
SaveLoadEntity[] entities = new SaveLoadEntity[entitiesCount];
for (int j = 0; j < entities.Length; j++)
{
string uniqueID = ES3.Load<string>("SaveLoadEntity_" + j + "ID", settings);
SaveLoadEntity sleFound = null;
foreach (EquipmentType sle in EquipmentType.AllTypes)
{
SaveLoadEntity entity = sle.SimulationPrefab.GetComponent<SaveLoadEntity>();
if (entity != null && entity.UniqueID == uniqueID)
{
sleFound = entity;
break;
}
}
Debug.Log("SaveLoadSite: Loading entity - " + sleFound.ToString());
if (sleFound)
{
entities[j] = Instantiate(sleFound, Site.transform);
if (Application.isPlaying)
{
//get the instances NetworkObject and Spawn
NetworkObject newCharNO = entities[j].GetComponent<NetworkObject>();
newCharNO.Spawn();
newCharNO.TrySetParent(Site.transform);
}
else
{
entities[j].transform.SetParent(Site.transform);
}
//load in all the entity components that do not reference other components
for (int k = 0; k < entities[j].Components.Length; k++)
{
if (ES3.KeyExists("Component_" + j + "_" + entities[j].Components[k].SLC_UniqueName, settings))
{
Debug.Log("SaveLoadSite: Loading component - " + entities[j].UniqueID + " - " + entities[j].Components[k].SLC_UniqueName + " - " + entities[j].Components[k].SavedComponent);
ES3.LoadInto("Component_" + j + "_" + entities[j].Components[k].SLC_UniqueName, entities[j].Components[k].SavedComponent, settings);
}
}
}
else
{
Debug.LogError("SaveLoadSite: Entity not found when loading: " + uniqueID, gameObject);
}
yield return new WaitForSeconds(0.1f);
}
Code: Select all
SaveLoadSite: Loading component - LaunchComplex - GridOccupant - Launch Complex Simulation(Clone) (GridOccupant)
UnityEngine.Debug:Log (object)
SaveLoadSite/<StartLoad>d__12:MoveNext () (at Assets/Scripts/SaveLoad/SaveLoadSite.cs:236)
UnityEngine.SetupCoroutine:InvokeMoveNext (System.Collections.IEnumerator,intptr)
Thank you in advance for any help or pointers in the right direction!
Code: Select all
public class SaveLoadSite : MonoBehaviour, ISaveLoadHandler
{
public string UniqueID => m_Site.UniqueID;
private string FileName = "_Site.lbs";
public Site Site => m_Site;
[SerializeField] private Site m_Site;
[SerializeField] private List<Component> m_SaveLoadComponents;
public bool SaveLoadInProgress => m_SaveLoadInProgress;
private bool m_SaveLoadInProgress;
public IEnumerator StartNewGame()
{
m_SaveLoadInProgress = true;
yield return new WaitForSeconds(0.1f);
m_SaveLoadInProgress = false;
}
public IEnumerator StartSave(string folder)
{
//make sure there is a save folder
if (!ES3.DirectoryExists(folder))
{
yield break;
}
//make sure there is no core folder yet
if (ES3.FileExists(folder + UniqueID + FileName))
{
#if UNITY_EDITOR
if (EditorUtility.DisplayDialog("Overwrite Site File", $"A {UniqueID + FileName} site file already exists, do you want to overwrite it?", "Yes", "No"))
{
ES3.DeleteFile(folder + UniqueID + FileName);
}
else
{
yield break;
}
#else
Debug.LogError($"Tried to save when a {FileName} Site file already exists : " + folder);
yield break;
#endif
}
m_SaveLoadInProgress = true;
ES3Settings settings = new ES3Settings(ES3.Location.Cache);
settings.path = folder + UniqueID + FileName;
//save game version
ES3.Save("Version", Application.version, settings);
//save site information
ES3.Save("Site", m_Site, settings);
ES3.Save("SiteID", m_Site.UniqueID, settings);
ES3.Save("SiteBody", m_Site.Location.SOIName, settings);
//save the ores
ES3.Save("SiteOres", m_Site.GetComponentInChildren<OreHandler>().CeramicOreData, settings);
//make sure the site transform is included in the references and save the reference
ES3Internal.ES3ReferenceMgrBase.Current.Add(m_Site.transform);
ES3.Save("SiteTransformRef", ES3Internal.ES3ReferenceMgrBase.Current.Get(m_Site.transform), settings);
List<SaveLoadEntity> entities = m_Site.SaveLoadEntities;
ES3.Save("SiteEntityCount", entities.Count, settings);
for (int j = 0; j < entities.Count; j++)
{
SaveLoadEntity sle = entities[j];
ES3.Save("SaveLoadEntity_" + j + "ID", sle.UniqueID, settings);
for (int k = 0; k < sle.Components.Length; k++)
{
for (int l = 0; l < sle.Components.Length; l++)
{
if (k != l && sle.Components[k].SLC_UniqueName == sle.Components[l].SLC_UniqueName)
{
GameObject tracePoint = sle.Components[k].SavedComponent.gameObject;
Debug.LogError("Saving component with non-unique uniqueID : " + sle.gameObject.name + " : " + sle.UniqueID + " : " + sle.Components[k].SLC_UniqueName + " : " + DebugHelper.HierarchyTrace(tracePoint));
break;
}
}
if (sle.Components[k] == null) { Debug.LogError("Tried saving a null reference : " + sle.gameObject.name + " : " + sle.UniqueID); break; }
ES3.Save("Component_" + j + "_" + sle.Components[k].SLC_UniqueName, sle.Components[k].SavedComponent, settings);
}
}
//Save the sites SaveLoadComponents
for (int i = 0; i < m_SaveLoadComponents.Count; i++)
{
ISaveLoadComponent slc = (ISaveLoadComponent)m_SaveLoadComponents[i];
if (slc == null) { Debug.LogError("SaveLoadSite: Missing ISaveLoadComponent on " + m_SaveLoadComponents[i].name); continue; }
ES3.Save(slc.SLC_UniqueName, slc, settings);
}
//load the parts information
ES3.Save("SiteParts", PartRoutingController.GetControllerForSite(m_Site), settings);
ES3.StoreCachedFile(settings);
yield return new WaitForSeconds(0.1f);
//clear file from cache
ES3.DeleteFile(settings);
yield return new WaitForSeconds(0.1f);
m_SaveLoadInProgress = false;
}
public IEnumerator StartLoad(string folder)
{
while (string.IsNullOrEmpty(UniqueID))
{
//wait for Sites file to finish loading
Debug.Log("SaveLoadSite: Waiting for UniqueID to be loaded");
yield return new WaitForSeconds(1);
}
if (!ES3.FileExists(folder + UniqueID + FileName))
{
//incomplete path or no file found, assume this is a new game
Debug.Log("SaveLoadSite: File not found - " + folder + UniqueID + FileName);
yield break;
}
m_SaveLoadInProgress = true;
//Wait until we are sure the network is ready to handle loading
while (Application.isPlaying && !NetworkManager.Singleton.IsClient && !NetworkManager.Singleton.IsServer)
{
Debug.Log("SaveLoadSite: Waiting for network approval");
yield return new WaitForSeconds(5);
}
if (Application.isPlaying && !NetworkManager.Singleton.IsServer)
{
//only the server should load anything
Debug.Log("SaveLoadSite: Only the server can load save data");
yield break;
}
yield return new WaitForSeconds(0.1f);
ES3Settings settings = new ES3Settings(ES3.Location.Cache);
settings.path = folder + UniqueID + FileName;
ES3.CacheFile(folder + UniqueID + FileName);
ES3.LoadInto("Site", m_Site, settings);
OreHandler handler = m_Site.GetComponentInChildren<OreHandler>();
OreHandler.CeramicData[] data = ES3.Load("SiteOres", new OreHandler.CeramicData[0], settings);
handler.Clear();
handler.Generate(data);
Debug.Log("SaveLoadSite: Loaded Site Ores - " + data.ToString());
yield return new WaitForSeconds(0.1f);
//set the site transform as a reference
ES3Internal.ES3ReferenceMgrBase.Current.Add(m_Site.transform, ES3.Load<long>("SiteTransformRef", settings));
//find and generate each moon surface entity
int entitiesCount = ES3.Load<int>("SiteEntityCount", settings);
SaveLoadEntity[] entities = new SaveLoadEntity[entitiesCount];
for (int j = 0; j < entities.Length; j++)
{
string uniqueID = ES3.Load<string>("SaveLoadEntity_" + j + "ID", settings);
SaveLoadEntity sleFound = null;
foreach (EquipmentType sle in EquipmentType.AllTypes)
{
SaveLoadEntity entity = sle.SimulationPrefab.GetComponent<SaveLoadEntity>();
if (entity != null && entity.UniqueID == uniqueID)
{
sleFound = entity;
break;
}
}
Debug.Log("SaveLoadSite: Loading entity - " + sleFound.ToString());
if (sleFound)
{
entities[j] = Instantiate(sleFound, Site.transform);
if (Application.isPlaying)
{
//get the instances NetworkObject and Spawn
NetworkObject newCharNO = entities[j].GetComponent<NetworkObject>();
newCharNO.Spawn();
newCharNO.TrySetParent(Site.transform);
}
else
{
entities[j].transform.SetParent(Site.transform);
}
//load in all the entity components that do not reference other components
for (int k = 0; k < entities[j].Components.Length; k++)
{
if (ES3.KeyExists("Component_" + j + "_" + entities[j].Components[k].SLC_UniqueName, settings))
{
Debug.Log("SaveLoadSite: Loading component - " + entities[j].UniqueID + " - " + entities[j].Components[k].SLC_UniqueName + " - " + entities[j].Components[k].SavedComponent);
ES3.LoadInto("Component_" + j + "_" + entities[j].Components[k].SLC_UniqueName, entities[j].Components[k].SavedComponent, settings);
}
}
}
else
{
Debug.LogError("SaveLoadSite: Entity not found when loading: " + uniqueID, gameObject);
}
yield return new WaitForSeconds(0.1f);
}
for (int j = 0; j < entities.Length; j++)
{
if (entities[j])
{
//load in all the entity components that may reference another component a second time to ensure all references exist
for (int k = 0; k < entities[j].Components.Length; k++)
{
if (entities[j].Components[k].SLC_IncludesReferences)
{
if (ES3.KeyExists("Component_" + j + "_" + entities[j].Components[k].SLC_UniqueName, settings))
{
Debug.Log("SaveLoadSite: Loading refrencing component - " + entities[j].UniqueID + " - " + entities[j].Components[k].SLC_UniqueName);
ES3.LoadInto("Component_" + j + "_" + entities[j].Components[k].SLC_UniqueName, entities[j].Components[k].SavedComponent, settings);
}
}
}
yield return new WaitForSeconds(0.1f);
}
}
string version = ES3.Load<string>("Version", settings);
int buildVersion = int.Parse(version.Split('.')[1]);
//load again for the site anchors
ES3.LoadInto("Site", m_Site, settings);
//Load the sites SaveLoadComponents
for (int i = 0; i < m_SaveLoadComponents.Count; i++)
{
ISaveLoadComponent slc = (ISaveLoadComponent)m_SaveLoadComponents[i];
if (slc == null) { Debug.LogError("SaveLoadSite: Missing ISaveLoadComponent on " + m_SaveLoadComponents[i].name); continue; }
if (ES3.KeyExists(slc.SLC_UniqueName, settings))
{
Debug.Log("SaveLoadSite: Loading component - " + slc.SLC_UniqueName);
ES3.LoadInto(slc.SLC_UniqueName, slc, settings);
}
}
//load the parts information
ES3.LoadInto("SiteParts", PartRoutingController.GetControllerForSite(m_Site), settings);
yield return new WaitForSeconds(0.1f);
//clear file from cache
ES3.DeleteFile(settings);
yield return new WaitForSeconds(0.1f);
m_SaveLoadInProgress = false;
}
private void Awake()
{
SaveLoadManager.RegisterHandler(this);
}
private void OnDestroy()
{
SaveLoadManager.UnregisterHandler(this);
}
}