Inventory serialization error

Hi! I’m trying to create a save and load system for an inventory system I made. The way I’m trying to do it is serializing the list of Items (a serializable class) in binary format, but when I call the function “Save” located in the Inventory System script, it throws me an error, saying that “InventorySystem” is not serlialized, when it’s a Monobehaviour. I don’t know how to solve this problem, or even if this way is the propper way to do it. Please help me. :frowning:

Save Load System

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;

public static class SaveLoadSystem {
   
    public static void SaveInventory (InventorySystem inventario){
        BinaryFormatter bf = new BinaryFormatter ();
        FileStream archivo = new FileStream (Application.persistentDataPath + "/inventario.sav", FileMode.Create);

        InventoryData data = new InventoryData (inventario);

        bf.Serialize (archivo, data);
        archivo.Close ();
    }

    public static List<Items> LoadInventory (){
        if (File.Exists (Application.persistentDataPath + "/inventario.sav")) {
            BinaryFormatter bf = new BinaryFormatter ();
            FileStream archivo = new FileStream (Application.persistentDataPath + "/inventario.sav", FileMode.Open);

            InventoryData data = bf.Deserialize (archivo) as InventoryData;

            archivo.Close ();
            return data.itemsContenidos;
        } else {
            Debug.Log ("El archivo guardado no existe");
            return new List<Items> ();
        }
    }
}


[System.Serializable]
public class InventoryData{

    public List<Items> itemsContenidos;

    public InventoryData (InventorySystem inventario){
        itemsContenidos = new List<Items> ();
        for (int i = 0; i < inventario.inventario.Count; i++) {
            itemsContenidos.Add (inventario.inventario [i]);
        }
    }

}

Items Class

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public enum tiposItem {daga,espada,alabarda,pocionHP,pocionMana,armadura}

[System.Serializable]
public class Items {
   
    public InventorySystem inventarioPerteneciente;

    // GENERAL
    public string nombre;
    public string descripcion;
    public Sprite sprite;

    // CONSUMIBLES
    public int cantidad;
    // POCIONES
    public int cantidadRecuperada;

    // ARMADURAS
    public float penalizacionAguante;
    [Range(1,3)]
    public int tier;
    public bool sloteada;
    public float vitalidad;
    public float mitigacion;

    // ARMAS
    // int tier;
    public bool isRare;
    public int rareza;
    public float critico;
    public float fuerza;
    public float velocidadDeAtaque;
    public float espiritu;
    public float ki;

    public int nivel = 1;
    public int nivelMax = 1;
    public int experienciaActual;
    public int experienciaTotal = 1000;
    public int experienciaMaxBase = 1000;

    public Items (int tier){
        this.tier = tier;
    }
    public Items (int tier, bool isRare){
        this.tier = tier;
        this.isRare = isRare;
    }

    public virtual void Usar(){
        Debug.Log ("Usando objeto base");
    }

    public virtual void ganarExp(int cantidad){
       
    }

}

Inventory System

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class InventorySystem : MonoBehaviour {

    public static InventorySystem script;

    void Awake(){
        script = this;
        DontDestroyOnLoad (transform.gameObject);
    }

    public delegate void AccionesInventario ();
    public event AccionesInventario ItemAdded; // Suscriptores: InventarioHUD.updateInventoryHUD
    public event AccionesInventario ItemRemoved; // Suscriptores: InventarioHUD.updateInventoryHUD

    public List<Items> inventario;
    public int inventarioCount = 0;
    public Estadisticas statsPlayer;
    public List<Armas> armaEquipada;
    public List<Armaduras> armaduraEquipada;

    public void addItem(Items objeto){
        if (inventario.Count < 20) {
            inventario.Add (objeto);
            objeto.inventarioPerteneciente = this;
            inventarioCount++;
            ItemAdded (); // Delegado añadir
        } else {
            Debug.Log ("Inventario lleno");
        }
    }

    public void removeItem(Items objeto){
        inventario.Remove (objeto);
        inventarioCount--;
        ItemRemoved (); // Delegado borrar
    }

    public void equiparArmadura(Armaduras armadura){
        if (armaduraEquipada.Count == 0) {
            armaduraEquipada.Add (armadura);
            removeItem (armadura);
        } else {
            addItem (armaduraEquipada [0]);
            armaduraEquipada.RemoveAt (0);
            armaduraEquipada.Add (armadura);
            removeItem (armadura);
        }
        changeStats ();
    }

    public void equiparArma(Armas arma){
        if (armaEquipada.Count == 0) {
            armaEquipada.Add (arma);
            removeItem (arma);
        } else {
            addItem (armaEquipada [0]);
            armaEquipada.RemoveAt (0);
            armaEquipada.Add (arma);
            removeItem (arma);
        }
        changeStats ();
    }

    // TESTING SAVE LOAD

    public void Save(){
        SaveLoadSystem.SaveInventory (this);
    }

    public void Load(){
        List<Items> loadedInventario = SaveLoadSystem.LoadInventory ();
        inventario.Clear ();
        foreach (Items item in loadedInventario) {
            inventario.Add (item);
        }
    }
}

I’ve never actually written code to save an inventory system (similar to yours), however I always imagined that I would save:

  1. either name or id of the item (which could later be looked up & retrieved)
  2. stack count, if relevant.
  3. slot / equip index, if relevant.
  4. any additional data that is item dependent (such as leveling up an item, affects only your item and not the item ‘template’ or what not).

That’s all I would used to save/load items.

Like, your item class has things in it like sprites & the inventory system… I dunno.

1 Like

Can you please post the actual error in complete? The problem is the line

public InventorySystem inventarioPerteneciente;

on line 10 in your Items class.
You can’t serialize that, monobehaviour’s are not serializable and there are other objects in your InventorySystem that are not serializable. Also the Sprite in your Items class is not serializable. You should only put out to disk the things you absolutely need, but the rest of the variables in your Items class are serializable. If you remove the InventorySystem and the Sprite it should work.

1 Like

Oh gawd you’re right, thank you very much. I’ll try to find a new way to make reference to my inventory, as far as I need it to use an item. Thanks again! ^^