Saving Multiple Object Locations Using Binary

Hello I’m currently working on a level editor and I’ve started to look at how to save information and at this moment in time I have created a simple system which can save a single object locations and allow you to load and save that data as you please. However in a level editor you will have more than object to save so I need to upgrade this system to handle multiple GameObjects but I’m not entirely sure how to go about it. I know that I’ll need to load the data from Arrays as well as save all the data into these arrays instead of single floats as I have it in the below system:

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

public class Wall : MonoBehaviour
{
    public float posX;
    public float posY;
    public float posZ;

    public Vector3 position;
    // Use this for initialization
    void Start ()
    {
        posX = this.transform.position.x;
        posY = this.transform.position.y;
        posZ = this.transform.position.z;
        position = new Vector3 (posX, posY, posZ);
        gameObject.transform.position = position;
        Debug.Log (position);
    }

    public void Save()
    {
        SaveLoadManager.SaveLevel (this);
    }

    public void Load()
    {
        float[] loadedLvl = SaveLoadManager.LoadLevel ();

        posX = loadedLvl [0];
        posY = loadedLvl [1];
        posZ = loadedLvl [2];

        position = new Vector3 (posX, posY, posZ);
        gameObject.transform.position = position;
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;

public static class SaveLoadManager
{
    public static void SaveLevel(Wall wall)
    {
        BinaryFormatter bf = new BinaryFormatter ();
        FileStream stream = new FileStream (Application.persistentDataPath + "/level.sav", FileMode.Create);

        LevelData data = new LevelData (wall);

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

    public static float[] LoadLevel()
    {
        if (File.Exists (Application.persistentDataPath + "/level.sav")) {
            BinaryFormatter bf = new BinaryFormatter ();
            FileStream stream = new FileStream (Application.persistentDataPath + "/level.sav", FileMode.Open);

            LevelData data = bf.Deserialize (stream) as LevelData;

            stream.Close ();
            return data.lvlData;
        }
        else
        {
            Debug.LogError ("File does not exist");
            return new float[3];
        }
        return null;
    }
}

[Serializable]
public class LevelData
{
    public float[] lvlData;

    public LevelData(Wall wall)
    {
        lvlData = new float[3];
        lvlData [0] = wall.posX;
        lvlData [1] = wall.posY;
        lvlData [2] = wall.posZ;
    }
}

Anyone got some tips on where to start in upgrading this system or is it too simple to be improved for multiple GameObjects?

Cheers
MajorSmurf

It is simple, but that is fine. It’s generally a good idea to start simple, get it working and then then build it up step by step.

Maybe you could consider something like this :

  • Add a RegisterObject(Wall newWall) method to the SaveLoadManager.
  • In the SaveLoadManager add List<Wall> m_walls = new List<Wall>();
  • The RegisterObject method will simply add newWall into m_walls.
  • In the Start() method in the Wall script, call RegisterObject. This will create a list of all walls to be stored.
  • The SaveLevel method will now not be called from the Wall class (it could instead be called from, say, a GameManager object) and will take no parameters. It will iterate over m_walls saving each in turn.
  • The Load() on the Wall could take a LevelData object as parameter and set its position based on the float array contained within.
  • The LoadLevel will need to have some way of knowing how many walls to load and then load them (after first clearing out m_walls). For each wall loaded, construct a new Wall (you could either signal to the new Wall not to call RegisterObject in its Start() method, or, have the SaveLoadManager ignore registering objects during its ‘loading’ phase) and call the new Wall’s Load method.
  • Step this all through in the debugger. :slight_smile:

Something along those lines should work.

Thanks for the help I’ll see what I can come up with. Most likely a mess of errors but hey thats where the fun starts and the nightmares begins but ill be fine… i hope.