Help With Serialization

Started by
5 comments, last by jazzyspazglobal 7 years, 10 months ago

Hello, I am currently working to create a 2D platformer-like game and I am stumped on saving game data (Serialization). I understand what serialization is (To an extent) but I cannot get it to work.

Here is my serialization code:


        public void SavePlayerProfile()
        {
            IFormatter formatter = new BinaryFormatter();
            Stream stream = new FileStream("PlayerSaveData.bin", FileMode.Create, FileAccess.Write, FileShare.None);
            formatter.Serialize(stream, this);
            stream.Close();
        }

And here is my deserialization code:


        public PlayerProfile LoadPlayerProfile()
        {
            IFormatter formatter = new BinaryFormatter();
            Stream stream = new FileStream("PlayerSaveData.bin", FileMode.Open, FileAccess.Read, FileShare.Read);
            PlayerProfile p = (PlayerProfile)formatter.Deserialize(stream);
            stream.Close();
            return p; 
        }

Both of these work like a charm but the PlayerProfile object cannot be deserialized unless it is serialized within the same instance of the game. Once I close the project and try loading (Deserializing), it will throw a NullReferenceException. I truly hope the problem isn't something too obvious that I may be overlooking xD

Advertisement

Post your player profile class.

Your problem just might be that there is a pointer that needs to be patched or something.

Hi.

I'm not very experienced with serialization but, are you writing pointers (addresses) to the save file?

Because I'm thinking that they would indeed work on the same instance that saved it (because the addresses remain the same) but won't work when you run the game again because your PlayerProfile class pointers have different addresses.

Don't know if that's the issue, but that's the first thing that comes to mind.

By the way, I'm assuming that's C++, if it's not, then my mistake.

Hope it helps!

EDIT: Ha, Tangletail beat me to the punch. :)

That's C#, and the BinaryFormatter is capable of serializing cyclic digraphs (i.e. anything). Those functions should work as written. Can you post those your other code as well?

They will work, however your deserialization method should be static. How are you calling it? Are you making a PlayerProfile instance, deserializing the data, and then throwing away the return value? That would be your problem, if so.

The BinaryFormatter.Deserialize will create new objects; it won't fill in the fields of your existing object.

Here is my entire PlayerProfile Class:


    [Serializable]
    public class PlayerProfile
    {
        private int lives;
        private bool[] levelscompleted;
        public int Lives
        {
            get { return lives; }
            set { lives = value; }
        }
        public bool[] LevelsCompleted
        {
            get { return levelscompleted; }
        }
        
        public PlayerProfile()
        {
            lives = 3; 
        }
        public void SavePlayerProfile()
        {
            IFormatter formatter = new BinaryFormatter();
            Stream stream = new FileStream("PlayerSaveData.bin", FileMode.Create, FileAccess.Write, FileShare.None);
            formatter.Serialize(stream, this);
            stream.Close();
        }
        public PlayerProfile LoadPlayerProfile()
        {

            IFormatter formatter = new BinaryFormatter();
            Stream stream = new FileStream("PlayerSaveData.bin", FileMode.Open, FileAccess.Read, FileShare.Read);
            PlayerProfile p = (PlayerProfile)formatter.Deserialize(stream);
            stream.Close();
            return p; 
        }
    }

And here are my function calls:


            if (yes.isPressed())
            {
                if (File.Exists("PlayerSaveData.bin"))
                {
                    Game1.PlayerProfile = Game1.PlayerProfile.LoadPlayerProfile();
                }
                else
                {
                    Game1.PlayerProfile = new PlayerProfile();
                    Game1.PlayerProfile.SavePlayerProfile();
                }
                GSM.Change(Game1.PLAYGAME);
            }

There exists a static variable for PlayerProfile in my Game1 class, but it was left uninstantiated. I set it to a new PlayerProfile instance upon its initial creation and the code now works. Still going to post the above in case any other problems arise.

Here's what I would change:


public PlayerProfile LoadPlayerProfile()
->
public static PlayerProfile LoadPlayerProfile()

Game1.PlayerProfile = Game1.PlayerProfile.LoadPlayerProfile();
->
Game1.PlayerProfile = PlayerProfile.LoadPlayerProfile();
This will allow you to load the profile without instantiating a "placeholder" instance that gets overwritten immediately.

My personal habit is that any time I see a function that doesn't use any member variables of the class it's in, and isn't virtual, I make it static.

Here's what I would change:


public PlayerProfile LoadPlayerProfile()
->
public static PlayerProfile LoadPlayerProfile()

Game1.PlayerProfile = Game1.PlayerProfile.LoadPlayerProfile();
->
Game1.PlayerProfile = PlayerProfile.LoadPlayerProfile();
This will allow you to load the profile without instantiating a "placeholder" instance that gets overwritten immediately.

My personal habit is that any time I see a function that doesn't use any member variables of the class it's in, and isn't virtual, I make it static.

Thank you very much!

This topic is closed to new replies.

Advertisement