Unity data persistence - PlayerPrefs

Unity data persistence - PlayerPrefs

foreword

I believe that many friends who use unity for game development have headaches and lose a lot of hair because of such a file system! Then this time I will teach beginners how to make a file system about PlayerPrefs.

By the way, this is the first article I have shared, if there is anything wrong, please let me know in the comments, no nonsense, Let’s go.

What is PlayerPrefs

If you want to know exactly what PlayerPrefs is, I am 100% not authoritative, so please refer to the official documentation: https://docs.unity3d.com

OK, so what are PlayerPrefs? Simply put, PlayerPrefs is Unity's built-in API for storing data. It stores files in a default location on the hard disk. For details, please check the official documentation.

Advantages of PlayerPrefs

Because it is a built-in API of Unity, it is very simple to call, and it can be stored in the system with several built-in methods.

Disadvantages of PlayerPrefs

Although simple and easy to use, this PlayerPrefs can only store 3 data types: int, float, string, but it is basically enough

And the location where the PlayerPrefs are stored is the same, so the data can be easily changed

Use of PlayerPrefs

PlayerPrefs are somewhat similar to dictionaries and hash tables, and are used through key-value pairs

How to use it, or go directly to the case, it will be clearer

case

Create a new Unity3D or 3DURP, HDRP project, here I use the 2021.3.2LTS version, which is backward compatible to Unity2017

Renamed SampleScene to Info

Create a new empty object, name it Info, Reset Transfrom, then mount a script named SaveInfo, double-click to open it

Enter the following code

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

public class SaveInfo : MonoBehaviour
{
    public string playerName;
    public int age;

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.S))
        {
            //write each data
            PlayerPrefs.SetString("PlayerName", playerName);
            PlayerPrefs.SetInt("Age", age);
            PlayerPrefs.SetFloat("PosX", transform.position.x);
            PlayerPrefs.SetFloat("PosY", transform.position.y);
            PlayerPrefs.SetFloat("PosZ", transform.position.z);

            //save to hard drive
            PlayerPrefs.Save();
        }
        if (Input.GetKeyDown(KeyCode.L))
        {
            //read archive
            playerName = PlayerPrefs.GetString("PlayerName");
            age = PlayerPrefs.GetInt("Age");
            transform.position = new Vector3(
                PlayerPrefs.GetFloat("PosX"),
                PlayerPrefs.GetFloat("PosY"),
                PlayerPrefs.GetFloat("PosZ"));
        }
    }
}

After saving, return to Unity, click Run, then change the Transfrom.position and PlayerName and age of Info and press S. When re-running, press L to return to the state before pressing S.

When pressing S

After pressing L

It is the same when pressing S and after pressing L, it means there is no problem

Great, it worked, so how did this happen?

I'll give you a small task, check the official documentation (both in Chinese and English) and my comments, and see if you can understand it.

understand

In order for you to understand, please open that part of the code and read it while reading the code

PlayerPrefs.SetString("PlayerName", playerName);

The function of this line of code is to store a parameter of type String. The first one is called the key and the second one is called the value. If you know anything about dictionaries, you will say it!

However, it should be noted that the key can only be of type string (which is a bit different), and the value can only be of type string (because it is SetString)

Simply put, SetString stores data of type string through a value of type string, and SetInt stores data of type int through a value of string type. As for SetFloat, I think you already know

That

PlayerPrefs.Save();

what does it mean

In fact, although we set the value, but it is not actually written to the hard disk, so we need a line of code to write to the hard disk, yes, it is PlayerPrefs.Save();

I think it's not too difficult for you to understand GetXXX after you say SetXXX. Yes, it is to find the value of type XXX through a String key.

  • Insert a sentence, this has a double overload of GetXXX, the second overload requires you to fill in a default value

Use of PlayerPrefs and JsonUtility

The above is inconvenient to use, and the data types are limited, which is difficult for friends who like to be lazy or have other needs, so what should we do?

In fact, the data type is limited. We can recall how the decimal type is stored in C#. Yes, it is to convert an integer to a string type, so can other data types also do the same? of course of course

The inconvenient problem is also easy to solve. We write a Save singleton base class that inherits from Singleton and there is a method to do this.

Having said so much, your biggest problem is nothing more than how to convert data into string type. Then we need to understand a concept of Json. Some students may have heard of Json. Our next article is also dedicated to Json data persistence. So here is a brief introduction to what is Json

Json(JavaScript Object Notation) is a data exchange structure, itself a regular string

For more Json content, please check the information yourself, and we know enough

Save base class

singleton

There are thousands of ways to write a singleton, and there is no problem. Then I chose one way of writing. If you don't know what the singleton pattern is, please check the information yourself.

I write it as

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

public class Singleton<T> : MonoBehaviour where T : Component
{
    private static T instance;

    public static T Instance
    {
        get
        {
            if (instance == null)
            {
                var obj = new GameObject();

                obj.name = typeof(T).ToString();
                DontDestroyOnLoad(obj);

                instance = obj.AddComponent<T>();
            }
            return instance;
        }
    }
}


You can also choose other writing styles, that's all I have

Convert to Json string

There is a class in Unity that deals with Json strings called JsonUtility, official English documentation: https://docs.unity3d.com/ScriptReference/JsonUtility.html

Chinese documentation: https://docs.unity.cn/cn/current/ScriptReference/JsonUtility.html

The methods we will use are JsonUtility.ToJson and FromJson, as for FromJsonOverwrite next time

So what exactly are they used for?

JsonUtility.ToJson

Pass in a serializable parameter and return a Json string

JsonUtility.FromJson

Pass in a json string and return a class

specific spelling

Create a base class called Save

Write the following code

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

public class Save : Singleton<Save>
{
    //save
    public void SaveByPlayerPrefs(string key, object value)
    {
        var json = JsonUtility.ToJson(value);

        PlayerPrefs.SetString(key, json);
        PlayerPrefs.Save();
    }
		
    //read
    public string LoadByPlayerPrefs(string key)
    {
        return PlayerPrefs.GetString(key, null);
    }
}

Then add a class to the SaveInfo class, which contains the information to be saved. Note: Be sure to add a label [System.Serializable] to the class, otherwise it cannot be serialized

The whole script becomes

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

[System.Serializable]
public class Info
{
    public string playerName;
    public int age;
    public Vector3 pos;
}

public class SaveInfo : MonoBehaviour
{
    public string playerName;
    public int age;
    private Info info;
    void Awake()
    {
        info = new Info();
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.S))
        {
            //write each data
            info.playerName = playerName;
            info.age = age;
            info.pos = transform.position;

            Save.Instance.SaveByPlayerPrefs("PlayerInfo", info);
        }
        if (Input.GetKeyDown(KeyCode.L))
        {
            var playerInfo = Save.Instance.LoadByPlayerPrefs("PlayerInfo");

            info = JsonUtility.FromJson<Info>(playerInfo);
            playerName = info.playerName;
            age = info.age;
            transform.position = info.pos;
        }
    }
}

Save, go back to Unity, it's the same as before, beautiful, we're done, applaud ourselves 👏🏻

As for how to achieve it, I won't explain it here. It's not because people are lazy, but I hope everyone can read the source code more.

  • Digression: Edit-ClearAllPrefabs can clear all Prefabs. This step must be done before packaging the game to ensure that the game has zero archives.

Purpose of PlayerPrefs

The main purpose of PlayerPrefs is to store player settings. I believe you who have played games must know that you can set them in the game, and it doesn't matter if the settings are changed, so security is not so important!

Tags: C# Unity

Posted by itshim on Sun, 22 May 2022 01:26:11 +0300