1

I have a class, named Schematic, that stores a structure of blocks for use in my game. I'm trying to get a way to save and load them using the BinaryFormatter, however I have an issue with the deserialization. When I deserialize, I cannot cast to my source type, instead it only lets me get one field, a two dimensional array of integers.

Here's the code for the schematic class:

[Serializable]
public class Schematic
{
    public static Schematic BlankSchematic = new Schematic("BLANK");
    public int[,] Blocks;
    public V2Int Size;
    public V2Int Location = V2Int.zero;

    public string Name;

    //---PROPERTIES---
    //lower is more rare
    public int Rarity = 100;
    //---END PROPERTIES---

    public Schematic(string name)
    {
        Name = name;
    }
    public Schematic(string name, int[,] blocks)
    {
        Name = name;
        ModifyBlockArray(blocks);
    }
    public void ModifyBlockArray(int[,] newBlocks)
    {
        Blocks = newBlocks;
        Size = new V2Int(newBlocks.GetLength(0), newBlocks.GetLength(1));
    }
}

And my methods in a separate class for serialization and deserialization:

public void SaveSchematic(Schematic schem)
{
    using (Stream stream = new FileStream(SchematicsDirectory + "/" + schem.Name + ".schem", FileMode.Create, FileAccess.Write, FileShare.None))
    {
        BinaryFormatter bf = new BinaryFormatter();
        Debug.Log(schem.GetType());
        bf.Serialize(stream, schem);
    }

}

public void LoadSchematics(string dir)
{
    BinaryFormatter bf = new BinaryFormatter();

    DirectoryInfo info = new DirectoryInfo(dir);
    FileInfo[] fileinfo = info.GetFiles("*.schem");
    for (int i = 0; i < fileinfo.Length; i++)
    {
        FileStream fs = new FileStream(dir + fileinfo[i].Name, FileMode.Open);
        object tempO = bf.Deserialize(fs);
        Debug.Log(tempO + ", " + tempO.GetType());
        Schematic temp = (Schematic)tempO;
        SchematicsByName.Add(temp.Name, temp);
        Schematics.Add(temp);
        print("Loaded Schematic: " + temp.Name);
        fs.Close();
        fs.Dispose();
    }
}

It's very strange because when I look into a serialized file, I see the other fields and the class name "Schematic." Here is a small little example file:

    ÿÿÿÿ          Assembly-CSharp       Schematic   BlocksSizeLocationNameRarity System.Int32[,]V2Int   V2Int             V2Int   xy                            
TestSavingd                                           

V2Int is marked as Serializable as well. It's really weird that when I deserialize I get back the Blocks array and not the whole class. Any help would be much appreciated.

This is my first post on here, so sorry if I made any mistakes.

Visual Vincent
  • 18,045
  • 5
  • 28
  • 75
Xyag
  • 13
  • 2
  • I see no mistakes wherever I look, this is _**very**_ good for a first question! Great job! -- I added the Binary Serialization tag to it, thought it might be handy to specify the type of serialization already in the tags. – Visual Vincent Jul 17 '16 at 22:11
  • please post the definition of V2Int class as well – Raja Nadar Jul 17 '16 at 22:45

1 Answers1

0

I tried it with a sample snippet, and it serialized and deserialized correctly for me. Please ensure that the Schematic object being sent in has all the right values to start with. And in general,

the deserialized object is your best bet of the final values. don't look at the serialized file. also, if you had the wrong type deserialized, this line would have typically thrown a cast exception.

Schematic temp = (Schematic)tempO;

So please execute the following snippet and let us know. It worked alright for me. (I cooked up a random V2Int class based on its constructor)

    public static string SchematicsDirectory = "d:\\temp\\s";

    static void Main(string[] args)
    {
        var p = new Program();

        var array = new int[2, 2];
        array[0, 0] = 1;
        array[0, 1] = 2;
        array[1, 0] = 3;
        array[1, 1] = 4;

        var testObject = new Schematic("fezzik", array);

        p.SaveSchematic(testObject);
        p.LoadSchematics(SchematicsDirectory + "/");
    }

enter image description here

Raja Nadar
  • 9,409
  • 2
  • 32
  • 41
  • No idea why it wasn't working earlier, just tried it again(without changes) and now it works. Maybe my computer was just mad or something lol. Thanks for the reply. – Xyag Jul 17 '16 at 23:25
  • cool. as an additional input, you don't need to do fs.close, fs.dispose.. c# makes it easier using the 'using' keyword.. auto-disposable.. using (var fs = new FileStream(dir + fileinfo[i].Name, FileMode.Open)) { object tempO = bf.Deserialize(fs); Debug.Log(tempO + ", " + tempO.GetType()); Schematic temp = (Schematic)tempO; SchematicsByName.Add(temp.Name, temp); Schematics.Add(temp); print("Loaded Schematic: " + temp.Name); } – Raja Nadar Jul 18 '16 at 00:39