- Home /
Problem with saving List of objects !!!
Hello,
I have a problem that i fight with. Im trying to make something like lootbox when player can get item but when he get one, item is removed from list and player can't get the same thing anymore. But when i exit the game and start again list again has removed items so im trying to ad save script so program can remember witch items are removed but when i did it i have the same errors all the time.
When Save : SerializationException: Type 'UnityEngine.GameObject' in Assembly 'UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable. System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers (System.RuntimeType type) (at :0)
When Load : IOException: Sharing violation on path C:\Users\user1\AppData\LocalLow\DefaultCompany\project1\playerInfo.dat System.IO.FileStream..ctor (System.String path, System.IO.FileMode mode, System.IO.FileAccess access, System.IO.FileShare share, System.Int32 bufferSize, System.Boolean anonymous, System.IO.FileOptions options) (at :0)
{
public List<GameObject> item;
public void Loot_randoo()
{
int i = UnityEngine.Random.Range(0, item.Count);
item.SetActive(true);
item.Remove(item);
}
public void Save()
{
BinaryFormatter bf = new BinaryFormatter();
FileStream file = File.Create(Application.persistentDataPath + "/playerInfo.dat");
PlayerData_2 data = new PlayerData_2();
data.item_random = item;
bf.Serialize(file, data);
file.Close();
}
public void Load()
{
if (File.Exists(Application.persistentDataPath + "/playerInfo.dat"))
{
BinaryFormatter bf = new BinaryFormatter();
FileStream file = File.Open(Application.persistentDataPath + "/playerInfo.dat", FileMode.Open);
PlayerData_2 data = (PlayerData_2)bf.Deserialize(file);
file.Close();
item = data.item_random;
}
}
}
[Serializable]
class PlayerData_2
{
public List<GameObject> item_random;
}
Don't serialize gameobjects. First it might not work if they are prefabs, but you won't be able to create a class from them since you are not allowed to create new gameobjects yourself, only Instanciate them though unity.
Simply create a Serializable class that contains all the info you need about your loots.
Answer by Xamtox · Dec 05, 2019 at 02:38 PM
You cannot (and should not attempt to - it's simply an overkill) serialize a Unity's gameobject to file. GameObject contains LOTS of different information under the hood: vectors, components, instance info etc. There is no need to save all that garbage inside a bin file.
Without any voodoo you can serialize only simple data types and simple classes. So:
Create a class, add [Serializable] attribute, do NOT inherit class from mono.
Create fields for all data you want to save: id, position (x, y and z), rotation (x, y and z), active state, ...
Prior to saving create that class and provide all savedata it needs.
Save and load your class instead of gameobject.
Upon loading, read all savedata from deserialized class and send it to gameobject.
... And even that system might be an overkill for you. Maybe it would be sufficient to assign to each saveable gameobject a unique ID, save IDs list, load IDs and remove any redundant IDs from your existing list?
You will need a place to store 'gameobject-id' pairs, of course. Something like this:
[Serializable]
class ObjectAndId {
public GameObject Obj;
public int Id;
}
[CreateAssetMenu(menuName = "Data/ObjectsRepository ")]
class ObjectsRepository : ScriptableObject {
public List<ObjectAndId> objects = new List<ObjectAndId>();
}
Ok, so i should add unique ID but can i storage id in item for example and if i want remove item from list should i remove ID? I'm sorry im not great in coding.
Answer by Xamtox · Dec 06, 2019 at 08:25 AM
(sorry, I couldn't edit comment's text style, so I converted it to an answer).
Yeah, basically you don't have list of items, you have list of IDs of items you need. For example, you have a Box (id 1), a Ball (id 2) and a Star (id 3) gameobjects in your lootbox. Your lootbox list contains 3 IDs:if i want remove item from list should i remove ID?
{ 1, 2, 3 }
If you want to get a Ball from lootbox, you instantiate Ball gameobject and remove id 2 from list:
{ 1, 3 }
After this you're saving list to a file (int values are serializable) like you did with gameobjects.
Done! When you loading your file, overwrite default list { 1, 2, 3 } with saved list { 1, 3 }. In that case a Ball (id: 2) is missing inside a lootbox after game loading! It looks pretty simple, the only hard part is to tell the game which id corresponds to which item.
Look at the code from my original answer. It allows to create ScriptableObject
(Unity>Create>Data>ObjectsRepository) and store inside it any number of 'gameobject-id' pairs (you could use Dictionary, but unity has issues with it). All assignments are done via inspector.
The only thing you will need after is to link your ObjectsRepository with your lootbox (or whatever script used for gameobjects management). Write inside a script:
[SerializeField] ObjectsRepository repository;
And assign your scriptable object via inspector. If you have an ID and want to get a gameobject:
public Gameobject GetGameOjbectFromRepo (int id) {
var obj = repository.objects.Find(a=>a.Id = id);
return obj;
}
Use an ID when passing data around: id is your object representation, you don't need gameobjects until the point you need to instantiate one. When you looking inside a lootbox, you shouldn't think: "Oh, i have a Ball, a Box and a Star in my lootbox", you should think: "I have objects with ids 1, 2 and 3 inside my lootbox".
So, when player takes a Ball from lootbox: 1. Remove Ball id (2) from lootbox list. 2. Get corresponding gameobject: GetGameOjbectFromRepo(2) and do with the ball whatever you want (instantiate, modify, ...).
Obviously, it's not a very good example: there are public fields instead of properties, there aren't any null checks, all values are mutable... It's just a template you may use to create your own system.
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
How can I fix this error in my Candy Crush style game? 0 Answers
Distribute terrain in zones 3 Answers
I am getting a error CS0246: 1 Answer
I am having an error in my script 1 Answer