![]() |
| What You'll Be Creating |
By the end of the tutorial, you will have learned how to:
- save and load game data within Unity3D using serialization
- use static variables to persist data across scene changes
Let's Get Serial
The first thing we're going to do is to create some code that allows us to serialize our game data—that is, convert it to a format that can be saved and later restored. For this, let's create a C# script and call it SaveLoad. This script will handle all the saving and loading functionality.
We will reference this script from other scripts, so let's make it a static class by adding the word static between public and class. Let's also remove the : MonoBehaviour part, because we don't need to attach it to a GameObject. And since it no longer inherits from MonoBehaviour, let's delete the Start and Update functions.
The resulting code should look like this:
- using UnityEngine;
- using System.Collections;
- public static class SaveLoad {
- }
- using System.Collections.Generic;
- using System.Runtime.Serialization.Formatters.Binary;
- using System.IO;
We're now ready to serialize some data!
Making Serializable Classes
Now that our script has the ability to serialize, we are going to have to set up some classes to be serialized. If you think about a basic RPG, like Final Fantasy, it offers players the ability to create and load different saved games. So, create a new C# script called Game and give it some variables to hold three objects: a knight, a rogue, and a wizard. Change the code of this script to look like this:
- using UnityEngine;
- using System.Collections;
- [System.Serializable]
- public class Game {
- public static Game current;
- public Character knight;
- public Character rogue;
- public Character wizard;
- public Game () {
- knight = new Character();
- rogue = new Character();
- wizard = new Character();
- }
- }
- All basic data types (like
int,string,float, and bool). - Some built-in types (including
Vector2,Vector3,Vector4,Quaternion,Matrix4x4,Color,Rect, and LayerMask). - All classes inheriting from UnityEngine.Object (including
GameObject,Component,MonoBehavior,Texture2D, and AnimationClip). - Enums.
- Arrays and lists of a serializable type.
gameObject's GetComponent() function. Handy!Notice that it's referencing something called a Character? We don't have that yet, so let's create a new script to house this class, and call it Character:
- using UnityEngine;
- using System.Collections;
- [System.Serializable]
- public class Character {
- public string name;
- public Character () {
- this.name = "";
- }
- }
Now that our classes are set up to be saved and loaded, let's hop back over to our SaveLoad script and add the ability to save games.
Saving a Game's State
A "Load Game" menu usually shows a list of saved games, so let's create a List of type Game and call it savedGames. Make it a static List, so that there's only one list of saved games in our project. The code should look like this:
- using UnityEngine;
- using System.Collections;
- using System.Collections.Generic;
- using System.Runtime.Serialization.Formatters.Binary;
- using System.IO;
- public static class SaveLoad {
- public static List<Game> savedGames = new List<Game>();
- }
- public static void Save() {
- savedGames.Add(Game.current);
- BinaryFormatter bf = new BinaryFormatter();
- FileStream file = File.Create (Application.persistentDataPath + "/savedGames.gd");
- bf.Serialize(file, SaveLoad.savedGames);
- file.Close();
- }
In Line 4, we're creating a FileStream, which is essentially a pathway to a new file that we can send data too, like fish swimming downstream in a river. We use File.Create() to create a new file at the location we pass in as its parameter. Conveniently, Unity has a built-in location to store our game files (which updates automatically based on what platform your game is built to) that we can reference using Application.persistentDataPath.
Since we're creating a new file, however, we can't just say where the file is, we also have to cap off this pathway with the name of the actual file itself. There are two parts to this file:
- the file name
- the file type
Note: You can make the file type anything you want. For example, the Elder Scrolls series uses .esmas its file type. You could have as easily said savedGames.baconAndGravy.
In Line 5, we're calling the Serialize functionality of the BinaryFormatter to save our savedGames list to our new file. After that, we have the close the file that we created, in Line 6.
Badda bing, badda boom. Our games are saved.
Loading a Game's State
In the Save function, we serialized our list of saved games at a specific location. Conversely, the code to load our games should look like this:
- public static void Load() {
- if(File.Exists(Application.persistentDataPath + "/savedGames.gd")) {
- BinaryFormatter bf = new BinaryFormatter();
- FileStream file = File.Open(Application.persistentDataPath + "/savedGames.gd", FileMode.Open);
- SaveLoad.savedGames = (List<Game>)bf.Deserialize(file);
- file.Close();
- }
- }
Line 5 is a bit dense, so let's unpack it:
- The bf.Deserialize(file) call finds the file at the location we specified above and deserializes it.
- We can't just spit binary at Unity and expect it to work, however, so we convert (or cast) our deserialized file to the data type we want it to be, which in this case is a List of type Game.
- We then set that list as our list of saved games.
Note: The data type to which you cast the deserialized data can change depending on what you need it to be. For example, Player.lives = (int)bf.Deserialize(file);;.
Conclusion
Our SaveLoad script is now complete, and should look like this:
- using UnityEngine;
- using System.Collections;
- using System.Collections.Generic;
- using System.Runtime.Serialization.Formatters.Binary;
- using System.IO;
- public static class SaveLoad {
- public static List<Game> savedGames = new List<Game>();
- //it's static so we can call it from anywhere
- public static void Save() {
- SaveLoad.savedGames.Add(Game.current);
- BinaryFormatter bf = new BinaryFormatter();
- //Application.persistentDataPath is a string, so if you wanted you can put that into debug.log if you want to know where save games are located
- FileStream file = File.Create (Application.persistentDataPath + "/savedGames.gd"); //you can call it anything you want
- bf.Serialize(file, SaveLoad.savedGames);
- file.Close();
- }
- public static void Load() {
- if(File.Exists(Application.persistentDataPath + "/savedGames.gd")) {
- BinaryFormatter bf = new BinaryFormatter();
- FileStream file = File.Open(Application.persistentDataPath + "/savedGames.gd", FileMode.Open);
- SaveLoad.savedGames = (List<Game>)bf.Deserialize(file);
- file.Close();
- }
- }
- }
If you need a head-start with your game development, try the Unity3D templates available on Envato Market.
Written by Eric Daily
If you found this post interesting, please follow and support us.
Suggest for you:
Unity 5 Professional Guide - Develop a 2D Arkanoid Game!
Unity 5 Professional Guide - Mastering C# Programming!
Make VR Games in Unity with C# - Cardboard, Gear VR, Oculus
Learn to Code by Making Games - The Complete Unity Developer
Start Learning Unity3d by Making 5 Games from Scratch

No comments:
Post a Comment