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!