I'm building off of Sebastian Lague's videos on procedural planets, and I stopped where I was happy with what the scripts did. So I worked on procedurally generating a system with the planets based off of presets.
I got to saving these systems with AssetDatabase.Save and Load and when it didnt work to build I moved to formatting it to save the data. I used Binary formatting because it seemed simple and the easiest to find tutorials on how to do.
However when I attempt to save data I get
SerializationException: Type 'UnityEngine.Vector3' in Assembly 'UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable.
here's the scripts that cause the errors
Save script
using UnityEngine;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
[System.Serializable]
public class Vector3Ser // serializealbe Vector3
{
public float x, y, z;
}
[System.Serializable]
public static class SaveSystem
{
const string savesPath = "/Saves";
public static void Save<t>(t obj, string key)
{
BinaryFormatter bf = new BinaryFormatter();
string path = Application.persistentDataPath + savesPath;
Directory.CreateDirectory(path); // create path if it doesnt exist
FileStream stream = new FileStream(path + key, FileMode.Create);
bf.Serialize(stream, obj); // save obj
stream.Close();
}
public static void CreateFolder(string key)
{
string path = Application.persistentDataPath + savesPath;
Directory.CreateDirectory(path + key); // create folder at path
}
public static T Load<T>(string key)
{
BinaryFormatter bf = new BinaryFormatter();
string path = Application.persistentDataPath + savesPath;
T data = default;
if (File.Exists(path + key))
{
FileStream stream = new FileStream(path + key, FileMode.Open);
stream.Flush(); //no idea why its there but I found it somewhere and tried it
stream.Position = 0; //no idea why its there but I found it somewhere and tried it
data = (T)bf.Deserialize(stream); // save the deserialized file to a variable
stream.Close();
} else
{
Debug.LogError("Failed to load save at " + path + key);
}
return data; // return file/data
}
public static bool SaveExists(string key)
{
string path = Application.persistentDataPath + savesPath;
return File.Exists(path + key);
}
}
Data class that I'm attempting to save
[System.Serializable]
public class PlanetData
{
public string planetName;
public Vector3Ser planetPos;
public int planetID = -1;
public float planetRadius;
public bool[] noiseLayerEnabled;
public bool[] nLFirstLayerAsMask;
public NoiseSettings[] noiseLayerNoiseSettings;
public string indentifier;
public PlanetData(ShapeSettings sS, ColourSettings cS)
{
planetName = sS.name + "_" + cS.name; // load name
planetRadius = sS.planetRadius; // load radius and planet id
planetID = sS.planetID;
planetPos = new Vector3Ser(); // load planet pos
planetPos.x = sS.PlanetPos.x; // load planet pos values
planetPos.y = sS.PlanetPos.y;
planetPos.z = sS.PlanetPos.z;
noiseLayerEnabled = new bool[sS.noiseLayers.Length]; // initalize these values
nLFirstLayerAsMask = new bool[sS.noiseLayers.Length];
noiseLayerNoiseSettings = new NoiseSettings[sS.noiseLayers.Length];
for (int i = 0; i < sS.noiseLayers.Length; i++) // loop through all values in sS.noiselayers
{
noiseLayerEnabled[i] = sS.noiseLayers[i].enabled;
nLFirstLayerAsMask[i] = sS.noiseLayers[i].useFirstLayerAsAMask;
noiseLayerNoiseSettings[i] = sS.noiseLayers[i].noiseSettings;
}
indentifier = cS.indentifier;
}
}
script snipits used for saving
if (SaveSystem.SaveExists(universeKey))//check if it exists
{
universeSettings = SaveSystem.Load<UniverseSettings>(universeKey); // if it does load it
} else
{
universeSettings = new UniverseSettings(); // otherwise make a new instance
}
------------
string key = "/GeneratedScenes/" + SceneManager.GetActiveScene().name + "/" + "PlanetData_" + i + ".gameDat"; // Save location
planetData = new PlanetData(BarrenShapePrefab, BarrenColourPrefab);
if (SaveSystem.SaveExists(key)) //check if it exists
{
planetData = SaveSystem.Load<PlanetData>(key); // if it does load it
}
if (!SaveSystem.SaveExists(key)) // otherwise make a new instance
{
SaveSystem.Save(planetData, key);
}
if (universeSettings.planetNum != numOfPlanets) // check if the amount of planets is saved (other bits of code will set the num of planets to this value if loaded)
{
string universeKey = "/GeneratedScenes/" + SceneManager.GetActiveScene().name + "/" + "UniverseData" + ".gameDat";
universeSettings.planetNum = numOfPlanets; // set value
SaveSystem.Save(universeSettings, universeKey); // save values
}