- Home /
Storing list aka "save function"
So, I have this script using UnityEngine; using System.Collections; using System.Collections.Generic;
public class NewBehaviourScript : MonoBehaviour {
List<Position> mylist = new List<Position>();
int xpos = 5;
int ypos = 3;
// Use this for initialization
void Start () {
for (int i = 0; i < 100; i++)
{
int x = Random.Range(0, 6);
int y = Random.Range(0, 6);
int b = Random.Range(0, 3);
mylist.Add( new Position(x, y, b));
}
DisplayList();
}
void DisplayList()
{
foreach (Position pos in mylist)
{
if (pos.xpos == xpos && pos.ypos == ypos)
print(pos.block);
}
}
}
And its Position class
using UnityEngine;
using System.Collections;
public class Position {
public string position;
public int xpos, ypos, block;
public Position(int x, int y, int b)
{
xpos = x;
ypos = y;
block = b;
}
}
As you can see this is pretty basic class and list generation and i use this on for testing purposes so my question is: how to save this to file and load when i run application next time? I heard about xml but it wont save lists, others said use Unity serialization but i dont understand that because i cant see it saving to file. Pretty much I'am quite lost.
It will be for world generation and saving so any advice on improving this system. Currently DisplayList checks if x,y is free position.
Thanks.
X$$anonymous$$L can be quite "heavy" if you are justing saving coordinates and an int Why don't you simply read / write to / from a simple text file in which you write x y b
for each line ?
For sure xml files can be edited ! It's just simple text files whose data are formatted within tags (like HT$$anonymous$$L)
That's what I suggested you when I told you to save your data like x y b
each line (just replace x, y and b by the appropriate value naturally)
Take a look here if you want to learn about I/O operations with files.
Personally I prefer using X$$anonymous$$L, it's easy to implement and navigate. Anyway there are a ton of ways you can achieve what you're trying to do. I think what Hellium suggested would be the best way, or you could use binary files. You could also use JSON as a lighter alternative to X$$anonymous$$L.
Never use absolute path like this one, especially when you access to files which do not "belongs to you".
Use relative path from Application.dataPath
You application will be cross-platform moreover.
See doc here :
http://docs.unity3d.com/ScriptReference/Application-dataPath.html
$$anonymous$$ake sure the account you use on your computer has rights on the targeted folder.
What does a Debug.Log(Application.dataPath);
show ?
Answer by phoda · Jul 18, 2015 at 02:57 AM
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.IO;
public class NewBehaviourScript : MonoBehaviour {
List<string> mylist = new List<string>();
// Use this for initialization
void Start () {
for (int i = 0; i < 10; i++)
{
string a = "";
int x = Random.Range(0, 6);
int y = Random.Range(0, 6);
int b = Random.Range(0, 3);
a = x + "," + y + "," + b;
mylist.Add(a);
}
DisplayList();
}
void DisplayList()
{
StreamWriter file = new StreamWriter(Application.persistentDataPath + "/info.txt", true);
print(Application.persistentDataPath + "/info.txt");
for (int i = 0; i < mylist.Count; i++)
{
string a = mylist[i];
file.WriteLine(a);
print(a.Split(',')[0] + "," + a.Split(',')[1] + "," + a.Split(',')[2]);
file.Flush();
}
}
}
Ok here is finished code to store data to text file.
StreamWriter needs path + "/filename.txt"; also after StreamWriterVariableName.WriteLine(); you need StreamWriterVariableName.Flush(); so stream actually saves content to file
Hope it helps someone and big thanks to these guys that helped me.
Answer by Radetic · Jul 17, 2015 at 11:56 AM
Hi there,
As pointed out by Hellium, a simple text file with space separated values would be simpler for some thing and much lighter in memory size. That's what I would go for if your save file structure is not suppose to change after defined.
However, if you plan to have different versions and are willing to sacrifice file size to get it more human readable (even if only for debugging) you need to have a XmlWriter to which you append the values and then give it to a XmlSerializer.
https://msdn.microsoft.com/en-us/library/system.xml.xmlwriter%28v=vs.110%29.aspx
https://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializer%28v=vs.110%29.aspx
You may have to implement some methods describing how each field goes into the xml file, but it's all good when it's done. As for serializing the list, methods WriteElement and WriteValue from xmlwriter are your good friends.
Hope it helps
I need this file to load world and save when player saves (it will have roughly 500,000 positions x max will be about 100 and y 2k-10k. I just need some method to load variables from file so game uses them and save them when needed. So i dont need constant editing of file but ocasional and perfect method for me would be at string "x100y200" save int 2
In this case, Hellium's suggestion stands better. Open up (or create) a simple txt file and write lines to it. C# has a few tricks to read values from within a string, so reload the game state wouldn't be a huge task as well.
Sorry if iam bothering and probably will use text version but how real publishers prevent players from editing save files, players probably wouldnt bother with editing text file on android but it would be nice if its protected. Btw thanks alot guys
In cenarios where you don't want a simple user tempering with game data it's usually a good call to use binary formats (not human readable, though) or insert some redundancies in the file.
On the redundancies matter, suppose you store, in your case, 3 values ins$$anonymous$$d of 2. Your x and y would be the intended values and the last one some sort of checksum or error correcting code.
If you're familiar with bitwise operators, the exclusive or (XOR) would provide a nice simple way of checking if either x or y was altered since writing the save file.
If you're not familiar, just do something like z = x ^ y; to save and check it when loading (z == x^y)
Answer by Cherno · Jul 17, 2015 at 12:35 PM
You can use SerializerHelper to save and load data. Just ignore all the stuff about saving gameObjects, and add a variable that holds your list to the SaveGame class, and assign your list to the SaveGame instance when saving.
Does this mean i can create public Transform [,] grid and just save that grid with some values inside it?
Transform is a Type that is specific to Unity and as such is not serializable. The SerializeHelper explains the use of ISerializationSurrogate for such types, if you want to go down that route. However, it might be easier to find another workaround; it depends on how the transforms in that array are going to be used. Also note that multidimensional arrays are not serializable either; you have to flatten them, but this is trivial. SerializeHelper also explains how to do this.
Edit: if all you want to save are Vector3 positions, then do this ins$$anonymous$$d; There is already a sample ISerializationSurrogate for Vector3 included. If you also want to save rotation and scale, then create a custom class that mirrors the variables of a Transform class (Vector3 for position, Vector3 for eulerAngles, (or Quaternion for rotation), and Vector3 for scale. $$anonymous$$ake this class [System.Serializable] and then you can save it.
Your answer
Follow this Question
Related Questions
Trying to XML serialize objects, getting error that UnityEngine.Transform doesn't implement Add() 1 Answer
Need experienced opinion: Saving a players inventory: XML or PlayerPrefs? 1 Answer
Questions about XML serialization of Class Properties 1 Answer