Saving and loading data can be done by writing and reading variables to and from a file. I will get to how you can do that later, but just a quick explanation on files.
Files can store data that contain text. This text could be a string, a number, a bool or byte etc. It’s important to note that not all data types can be converted to a string perfectly. Therefore, we need to save a string that represents that data type, and when we read the file, we need to interpret that string correctly.
Let’s take the example of saving the position of a game object to a file. You can’t save the transform of the object, but you can save 3 floats that contain the x, y and z position of the object. Or use Vector3.ToString().
Reading and Writing from/to a file
You need to be using System.IO
to perform operations on files.
Reading a file
You can use the File
class to read all lines from the file into a single string, or use the StreamReader
to read the file line by line, and perform operations on the line that is currently being read by the stream reader. For example:
void ReadFile(string directory)
{
// Getting raw text
string text = File.ReadAllText(directory);
// Using a stream reader
StreamReader reader = new StreamReader(directory);
string line;
while ((line = reader.ReadLine()) != null)
{
if (line == "Line 4: ")
{
// Do stuff
}
// etc.
}
}
Writing to a file
You can write to a file using the File
class or by using the StreamWriter as well:
void WriteToFile(string directory)
{
// Overwrites any text already in the file
File.WriteAllText(directory, "Hello world");
// Adds on to the end of an existing file
File.AppendAllText(directory, "Hello world");
// Overwrites any text already in the file
StreamWriter writer = new StreamWriter(directory);
writer.Write("Hello world");
}
If the file does not exist already, it will be created. Nice.
Saving your data
To save the scriptable objects, it would be good practice to go through every object, save the index of that object in the list, then underneath, save its properties, then leave a space for the next object. Here’s an example:
Scriptable object called Item:
[CreateAssetMenu(fileName = "New Inventory")]
public class Item : ScriptableObject
{
public string Name;
public int ID;
public float Price;
public Vector3 Position;
}
Class called ‘Backpack’ with a list of scriptable objects called inventory:
public class Backpack : MonoBehaviour
{
public List<Item> Inventory;
}
The Save() method would look something like this:
void SaveInventory(string directory)
{
for (int i = 0; i < Inventory.Count; i++)
{
Item item = Inventory*;*
File.AppendAllText
(
// Saves object index
directory, "Object " + i.ToString() + "
" +
// Saves object properties
item.name + "
" +
item.ID.ToString() + "
" +
item.Price.ToString() + "
" +
*item.Position.ToString() + "
"*
);
}
}
And the Load() method would look something like this:
void LoadInventory(string directory)
{
StreamReader reader = new StreamReader(directory);
string text = reader.ReadToEnd();
// Remember to close the stream IMPORTANT!
reader.Close();
string[] lines = text.Split(’
');
for (int i = 0; i < lines.Length; i++)
{
// Is a new object
if (lines*.Contains(“Object”))*
{
// Get properties
string name = lines[i + 1];
int id = int.Parse(lines[i + 2]);
float price = float.Parse(lines[i + 3]);
Vector3 position = StringToVector3(lines[i + 4]);
// Create new scriptable object and add to inventory
Item item = ScriptableObject.CreateInstance();
item.Name = name;
item.ID = id;
item.Price = price;
item.Position = position;
Inventory.Add(item);
}
}
}
Vector3 StringToVector3(string sVector)
{
// Remove the parentheses
if (sVector.StartsWith(“(”) && sVector.EndsWith(“)”))
{
sVector = sVector.Substring(1, sVector.Length - 2);
}
// split the items
string[] sArray = sVector.Split(‘,’);
// store as a Vector3
Vector3 result = new Vector3(
float.Parse(sArray[0]),
float.Parse(sArray[1]),
float.Parse(sArray[2]));
return result;
}
----------
Let me know if this works or not, and I’ll try to help. @SaintA721