Persistent Data

This entry is part 3 of 4 in the series Space Game

Previously on Space Game. . .

Last time I learned a lot about changing scenes and implemented all kinds of new scenes that you can switch between. That still left me a lot on my list to work on. But this time I’m going to learn something else, Data Persistence. I’ll be exploring ways to save and load data between scenes and sessions.

  • Ship rotation
  • Correct thrust mechanic
  • Camera Zoom
  • Pause Menu
  • Main Menu
  • Shipyard
  • Enemies
  • UI
    • Objective indicator
  • Ship shield/armor

And Now on Space Game . . .

I’m starting with a long video tutorial on the idea of a persistent game object between scenes. I followed along directly, but then made some modifications as I saw fit. Next up was the idea of saving data between game sessions. And of course, we need player preferences too.

The Script

The script itself is pretty simple. As you can see below we can set variables that will persist through scenes. There’s also the awake function which allows for only a single instance of this game object to exist.

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

public class GameControl : MonoBehaviour
{
	public static GameControl control;

	// Set your persistent variables here:
	public float health;

	void Awake()
	{
		if(control == null)
		{
			DontDestroyOnLoad(gameObject);
			control = this;
		}
		else if(control != this)
		{
			Destroy(gameObject);
		}
	}
}

The Game Object

Now that we’ve got our script we need it to exist in the world, so just create an empty object in your scene and then drag the script onto it. Pretty simple. Once that’s done, turn it into a prefab and then drag that to all your other scenes. Any variable you have created in that script will follow the game object from scene to scene and in each scene those variables will all be accessed the same way.

Saving

Now if you’re anything like me, you not only want data to persist between scenes in the game, but you’d also like to save it between games. We can do this in the same script we already have setup for persistent data. To do this, we’ll need to use a few extra namespaces. Just add these lines at the top with the rest:

using System;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;

Next up, we need to get the data setup in a way to allow saving. To do this we have to create a new class to hold the data and allow serialization. The following goes at the end of the unity script, after the final curly bracket:

[Serializable]
class PlayerData
{
    //List your persistent variables here:
    public float health;
}

Then we need to actually create a new function to save the data to a file. Keep in mind I don’t htink this will work for web games. I’m sure there are other ways to do this, but this tutorial is pretty good at going over everything I want. So, my save function (which goes inside the GameControl function) looks like this:

public void Save()
    {
        BinaryFormatter bf = new BinaryFormatter();
        FileStream file = File.Create(Application.persistentDataPath + "/playerinfo.dat");
        PlayerData data = new PlayerData();
        //List your persistent variables here:
        data.health = health;
        bf.Serialize(file, data);
        file.Close();
    }

Loading

Saving data is great, but pretty pointless if there’s no way to load it. So now we need a function to do just that. It’s a pretty straightforward addition to the script. Just add this bit to the end of the GameControl function:

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 data = (PlayerData)bf.Deserialize(file);
            file.Close();
            //List your persistent variables here:
            health = data.health;
        }
    }

Save / Load

That’s pretty much all there is, except now you need to actually run those functions. There’s many ways you could do that. The simplest would be to add buttons to your pause screen. Or you could use the awake function to load and have some sort of autosave feature built in. It’s up to you how you want to do it, but to actually call Save and Load, just look below:

//To Save
GameControl.control.Save();

//To Load
GameControl.control.Load();

Next Time . . .

There we have it, a simple say to keep data persistent between scenes and a way to save data between sessions. Obviously for me there will be a lot more to do with these functions. I don’t have any idea what data I’m going to be saving yet, so I’ll be editing the script regularly as I figure that out. I was going to go into playerprefs, but this turned out longer than I wanted to, and playerprefs will be used for game settings so we can look into that another day.

  • Ship rotation
  • Correct thrust mechanic
  • Saving/Loading
  • Persistent Data
  • Camera Zoom
  • Pause Menu
  • Main Menu
  • Shipyard
  • Enemies
  • UI
    • Objective indicator
  • Ship shield/armor

The Script

For those interested in the entire script that I created here, see below:

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

public class GameControl : MonoBehaviour
{
    public static GameControl control;

    // Set your persistent variables here:
    public float health;
    
    void Awake()
    {
        if(control == null)
        {
            DontDestroyOnLoad(gameObject);
            control = this;
        }
        else if(control != this)
        {
            Destroy(gameObject);
        }
    }

    public void Save()
    {
        BinaryFormatter bf = new BinaryFormatter();
        FileStream file = File.Create(Application.persistentDataPath + "/playerinfo.dat");
        PlayerData data = new PlayerData();
        //List your persistent variables here:
        data.health = health;
        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 data = (PlayerData)bf.Deserialize(file);
            file.Close();
            //List your persistent variables here:
            health = data.health;
        }
    }
}

[Serializable]
class PlayerData
{
    //List your persistent variables here:
    public float health;
}
Series Navigation<< Turning It AroundHex Grids and You >>

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.