说来惭愧,之前甚至连这个都没学
用文件的形式存储,其实有很多种不同办法都能实现。
但是这学期时间有限,所以打算学习其中的四种,目前只是做demo,所以使用的方法都是小白级别的。
存储读取数据只有对应的三种方法,非常方便。缺点是只能存储三种数据形式——int float string
使用就只有一种套路:
//在Player preference里面存入对应三种不同数据形式的键值对
PlayerPrefs.SetInt/SetFloat/SetString(String name,不同数据类型对应的值);
//在Player preference中查找对应键的值并返回
PlayerPrefs.GetInt/GetFloat/GetString(String name);
在场景里面新建一个文本框,里面是我们要保存的数据,然后建立一个保存按钮和一个加载按钮。当按下空格的时候,里面的数字+1。
书写ScoreAdd脚本,脚本随便挂载到一个物体上,并且把Text拖拽到脚本numText对象赋值;
使得按下空格的时候分数+1,
public class scoreAdd: MonoBehaviour
{
private int num;
public Text numText;
private void Awake() {
num = 0;
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Space)) {
num++;
Debug.Log("Score added");
numText.text = num.ToString();
}
}
}
为了让其他脚本能读取到num的数据,我们对scoreAdd脚本修改一下,把num改为public类型并且开启单例让其他脚本能访问到它。
public class scoreAdd : MonoBehaviour
{
public static scoreAdd instance;
public int num;
public Text numText;
private void Awake() {
if (instance == null) {
instance = this;
}
}
void Update()
{
numText.text = num.ToString();
if (Input.GetKeyDown(KeyCode.Space)) {
num++;
Debug.Log("Score added");
}
}
}
然后我们建立新的脚本usePlayerPrefs,书写如下代码。
public class usePlayerPrefs : MonoBehaviour
{
public void playerPrefsSave() {
PlayerPrefs.SetInt("MyScore", scoreAdd.instance.num);
Debug.Log("Score has saved");
}
public void playerPrefsLoad() {
scoreAdd.instance.num = PlayerPrefs.GetInt("MyScore");
Debug.Log("Score had loaded");
}
}
然后也是随便拖到一个物体上
在inspector给Save按钮OnClick添加playerPrefsSave事件;
Load按钮添加playerPrefsLoad事件
然后运行游戏,先把数字加到任意一个数,(我选择8)
按下Save。
重新开始场景
按下Load按钮,发现数字变为8,(~ ̄▽ ̄)~
相比于PlayerPres,只需要创建一个类来存储数据,存储的时候将其序列化成二进制文件(序列化),读取的时候将其反序列为类。
并且由于是二进制格式存储,玩家比较难篡改(大概)。
1.序列化
Serialization
将对象的状态信息转换为Unity可以存储文件的形式的自动化处理过程,或者简单来说是把对象转化为可传输的字节序列的过程。
2.文件
File
C#中的静态类,对文件进行操作:复制、创建、删除、移动(需要引入空间System.IO)
3.文件流
FileStream
对文件进行:读、写、关闭(需要引入空间System.IO)
反正就是需要什么操作就用什么类的函数
然后我们进行存储和读取的时候,借助一个类。
存储的时候新建一个类的对象,在这个类里面存放需要存放的数据,并把其序列化为一个二进制文件(也可以是其他类型),然后放进一个路径(一般都是Applicaiton.persistentDataPath);
读取的时候调用反序列化函数把这个文件变为之前的类就好了,(需要强制转化为之前类的类型)
要注意的是,需要引入命名空间 System,才能把这个类声明为可序列化。
using System;
///
/// 用于序列化成二进制文件的类
///
[Serializable]
public class Save
{
public int Score;
}
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using UnityEngine;
public class useSerialization : MonoBehaviour
{
///
/// 创建一个保存了数据的类
///
///
Save createSave() {
Save save = new Save();
save.Score = scoreAdd.instance.num;
return save;
}
public void serializationSave() {
Save save = createSave();
//Inheritance Object -> BinaryFormatter
BinaryFormatter bf = new BinaryFormatter();
//创建存档文件
FileStream fs = File.Create(Application.persistentDataPath + "/Data.text");
//将save变为fs
bf.Serialize(fs, save);
fs.Close();
}
public void serializationLoad() {
if(File.Exists(Application.persistentDataPath + "/Data.text")) {
BinaryFormatter bf = new BinaryFormatter();
//打开对应路径的存档文件
FileStream fs = File.Open(Application.persistentDataPath + "/Data.text",FileMode.Open);
Save save = bf.Deserialize(fs) as Save;
fs.Close();
scoreAdd.instance.num = save.Score;
} else {
Debug.LogWarning("Not Found Save File");
}
}
}
和PlayerPrefs一样,同样让两个按钮的OnClick添加对应的save和load委托。
同样加到8,按下save
重新开始
按下Load按钮,发现数字变为8,(~ ̄▽ ̄)~
还有另外一个会继续更新,先更到这
接下来是Json和XML
不要被看起来高大上的名字吓跑,在Unity上利用Json进行数据读写并不困难。
JSON全称 JavaScript Object Notation 也就是一种符号表示法。相比于序列化为二进制文件,JSON把对象存储为JSON文件,本质是字符串。
具体规则自行查找。
JSON同样以键值对的形式表示数据,string类型的键, int、bool、float 数组、对象的值
利用JSON和利用序列化存档的本质类似:
存储的时候新建一个类的对象,在这个类里面存放需要存放的数据,并利用JsonUtility 把其转化为一个JSON规则的字符串,再利用 StreamWriter生成文件,最后放进一个路径(一般都是Applicaiton.persistentDataPath);
读取的时候借助JsonUtility把这个文件变为之前的类就好了(泛型方法)。
using System;
///
/// 用于序列化成二进制文件的类
///
[Serializable]
public class Save
{
public int Score;
}
using System.IO;
using UnityEngine;
public class useJson : MonoBehaviour
{
///
/// 创建一个保存了数据的类
///
///
Save createSave() {
Save save = new Save();
save.Score = scoreAdd.instance.num;
return save;
}
public void jsonSave() {
Save save = createSave();
//Inheritance Object -> Json
string jsonString = JsonUtility.ToJson(save);
//创建StreamWrite,作用类似于类似于FileStream,生成存档文件
StreamWriter sw = new StreamWriter(Application.persistentDataPath + "/JsonData.txt");
sw.Write(jsonString);
sw.Close();
Debug.Log("Use Json to save project successed");
}
public void jsonLoad() {
if(File.Exists(Application.persistentDataPath + "/JsonData.txt")) {
StreamReader sr = new StreamReader (Application.persistentDataPath + "/JsonData.txt");
string JsonString = sr.ReadToEnd();
sr.Close();
Save save = JsonUtility.FromJson<Save>(JsonString);
//接下来要做什么操作自己决定
scoreAdd.instance.num = save.Score;
Debug.Log("Json Load successed");
} else {
Debug.Log("Not found Json Save File");
}
}
}
和PlayerPrefs一样,同样让两个按钮的OnClick添加对应的save和load委托。
加到8,按下save
重新开始
按下Load按钮,变成8了ヾ(✿゚▽゚)ノ
XML:Extensible Markup Language: 可扩展标记语言
不同系统之间的数据传输和交换非常消耗时间,并且可能产生一些丢失数据的情况。而XML以纯文本格式进行存储,使得在不同系统之间交换数据方便。本质就是字符串。
由于Unity没有自带解析XML的系统,所以我们需要借助Csharp的System.Xml来操作
存储的时候新建一个类的对象,在这个类里面存放需要存放的数据,然后构造一个XmlDocument类型的对象,设立一个根结点,对于需要存放的数据构造XmlElement类型的键值对,并且作为根结点的子结点,最后再将根结点作为对象的子结点,最后保存文件放进一个路径(一般都是Applicaiton.persistentDataPath);
读取的时候需要根据之前存放的键值对的值取到对应的数据。
略,和前面一样
using UnityEngine;
using System.IO;
using System.Xml;
public class useXML : MonoBehaviour
{
///
/// 创建一个保存了数据的类
///
///
Save createSave() {
Save save = new Save();
save.Score = scoreAdd.instance.num;
return save;
}
public void saveByXML() {
Save save = createSave();
XmlDocument xmlDocument = new XmlDocument();
#region CreateXML elements
XmlElement root = xmlDocument.CreateElement("Save");
//也不知道有什么用
root.SetAttribute("FileName", "File_01");
XmlElement scoreElement = xmlDocument.CreateElement("Score");
//设置元素值
scoreElement.InnerText = save.Score.ToString();
root.AppendChild(scoreElement);
#endregion
//将根结点和其子结点加入前面新建的XML文件
xmlDocument.AppendChild(root);
xmlDocument.Save(Application.dataPath + "/XMLData.text");
if (File.Exists(Application.dataPath + "/XMLData.text")) {
Debug.Log("XML file save successed");
}
}
public void loadByXML() {
if (File.Exists(Application.dataPath + "/XMLData.text")) {
Save save = new Save();
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.Load(Application.dataPath + "/XMLData.text");
//从XML中获得游戏数据
XmlNodeList score = xmlDocument.GetElementsByTagName("Score");
//score只有一个,所以是0号元素
int number = int.Parse(score[0].InnerText);
//获得数据赋予Save类
save.Score = number;
scoreAdd.instance.num = number;
} else {
Debug.Log("Load Failed");
}
}
}
同样加到8,并且保存
重新启动
按下Load按钮,变成8了ヽ(゚∀゚)メ(゚∀゚)ノ
其实没有必要四个都会,精通一个就好了,现在觉得应该是json最适合目前的我。