Unity零基础到入门☀️| 万字教程 讲解Unity中的数据存储 PlayerPrefsXMLJSON建议收藏

Posted 呆呆敲代码的小Y

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity零基础到入门☀️| 万字教程 讲解Unity中的数据存储 PlayerPrefsXMLJSON建议收藏相关的知识,希望对你有一定的参考价值。

  • 📢博客主页:https://blog.csdn.net/zhangay1998
  • 📢欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!
  • 📢本文由 呆呆敲代码的小Y 原创,首发于 CSDN🙉
  • 📢未来很长,值得我们全力奔赴更美好的生活✨


📢前言

  • 本文章是Unity零基础到入门专栏的系列文章
  • 适合对Unity3D引擎感兴趣的小伙伴学习,偏向于新手学习!
  • 本篇文章就来介绍一下Unity中三种基本的数据存储方式:PlayerPrefsXMLJSON
  • 由于是偏向于新手教程,所以不会介绍的很深刻,看完之后掌握 基本的数据读取 就足够了!
  • 下面一起来看一下吧!暂时没时间看可以直接点赞收藏不迷路,让你快速学会不加班!

🎬Unity中的三种数据存储

数据存储 也可以称为 数据持久化,不管是使用哪种语言、哪种开发工具
关于数据存储这一块对于整个项目以及开发团队来说都是非常重要的一块!

举个例子,我们在各种游戏里面充钱买装备、买皮肤等等操作的背后,都是有一个庞大的数据系统在支持。
一旦发生数据泄露、删库跑路等等事故,对公司来说也都是一个巨大的损失!

那本篇文章就来介绍一下在Unity中的数据存储常用的几种方式: PlayerPrefsXMLJSON

废话不多说,直接开始上干货了!


🎥PlayerPrefs

PlayerPrefs 是 Unity引擎 自身提供的一个用于本地持久化保存与读取的类

原理非常简单,以键值对的形式将数据保存在文件中,然后程序可以根据这个名称取出上次保存的数值。

PlayerPrefs类支持3种数据类型的保存和读取:浮点型整型字符串型

一共有上图中几种方法,下面来介绍一下分别的用法


🚩PlayerPrefs使用方法

保存数据

        //保存整型数据
        PlayerPrefs.SetInt("int1",123);
        //保存浮点型数据
        PlayerPrefs.SetFloat("float1",123.4f);
        //保存字符串型数据
        PlayerPrefs.SetString("string1","名字");

读取数据

        //读取整数型数据
        PlayerPrefs.GetInt("int1");
        //读取浮点型数据
        PlayerPrefs.GetFloat("float1");
        //读取字符串型数据
        PlayerPrefs.GetString("string1");

通过Key值取获取在本地持久化的数据,如果key值不存在 那么就会返回一个默认值

        //读取整数型数据,如果key值不存在 那么就会返回一个默认值0
        PlayerPrefs.GetInt("int1"123);
        //读取浮点型数据,如果key值不存在 那么就会返回一个默认值0.0
        PlayerPrefs.GetFloat("float1"123.4f);
        //读取字符串型数据,如果key值不存在 那么就会返回一个默认值""
        PlayerPrefs.GetString("string1""名字");

//查找是否存在该键值

PlayerPrefs.HasKey("int");

//清除所有记录

 PlayerPrefs.DeleteAll();

//删除其中某一条记录

PlayerPrefs.DeleteKey("int");

//将记录写入磁盘

PlayerPrefs.Save()

示例练习:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class PlayerPabsTest : MonoBehaviour
{
 
    // Use this for initialization
    void Start () {
        //写入姓名数据
        PlayerPrefs.SetString("姓名","张三");
        //查找是否存在键值为'姓名'的数据
        if (PlayerPrefs.HasKey("姓名"))
        {
            //读取键值为 '姓名' 的数据 并打印
            Debug.Log(PlayerPrefs.GetString("姓名"));
        }
    }
}

打印结果:


🚩不同平台的PlayerPrefs存储路径

  1. Mac OS X:~/Library/Preferences
  2. Windows:HKCU\\Software[company name][product name]
  3. Linux:~/.config/unity3d/ [CompanyName]/ [ProductName]
  4. Windows Store Apps: %userprofile% \\AppData\\Local\\Packages\\ [ProductPackageId]>\\LocalSt ate\\playerprefs.dat
  5. WebPlayer
    ✨Mac OS X: ~/Library/ Preferences/Unity/ WebPlayerPrefs
    ✨Windows: %APPDATA% \\Unity\\WebPlayerPrefs

以上就是Unity中自带的数据存储方法PlayerPrefs的介绍

PlayerPrefs的优点:可以快速便捷的处理一些数据,比XML、JSON等其他方法要快的多,对于开发者来说,读写也非常简单

PlayerPrefs的缺点:只能对整数型、浮点型和 字符串型 三种类型数据进行处理,如果遇上非常庞大的一个数据量就会非常麻烦且不利于管理

在开发平时的一些小项目 对数据存储功能没有强的需求时,使用效果很好!

注意:PlayerPrfs不同数据,不能同名,即便是不同的数据类型


🎥XML

先来简单了解一下 XML文件!

  • XML是⼀个⽂档 后缀名是*.xml
  • XML是⼀个特殊格式的⽂档
  • XML:是可扩展的标记性语言
  • XML是Extentsible Markup Language的缩 写
  • XML是由万维网联盟(W3C)创建的标记语言,用于定义编码人类和机器可以读取的文档的语法。它通过使用定义文档结构的标签以及如何存储和传输文档来实现这一点。

以上是我简单在网上搜了一下关于XML文件的介绍,我们简单了解一下XML文件的介绍就好
只需要知道可以利用XML文件来存储数据文件就够啦!


🏳️‍🌈XML的结构

先来看一下XML的结构

继承结构

XMLNode(节点类)

XMLNode 属性和方法说明
InnerText获取或设置结点及所有子节点的值(仅元素结点拥有)
Value获取或设置结点的值(仅元素结点拥有)
AppendChild将指定的结点添加到该节点的子节点列表的末尾
ChildNodes获取结点的所有子节点
FirstChild获取节点的第一个子节点
HasChildNodes判断该节点是否有任何子节点
SelectSingleNode选择匹配XPath表达式的第一个XmlNode
SelectSingleNodes选择匹配XPath表达式的所有XmlNode

XMLElement(XML元素类)

XMLElement 方法说明
SetAttribute设置具有指定名称的特性的值
HasAttributes判断该元素结点是否具有属性
GetAttribute返回具有指定名称的属性值

XMLDocument文档类

XMLDocument 方法说明
CreateXmlDeclaration创建一个具有指定值的XmlDeclaration节点
CreateElement创建具有指定名称的元素
CreateNode创建具有指定节点类型、Name和NamespaceURL的XMLNode
AppendChild将指定的节点添加到该节点的子节点列表的末尾(继承自XmlNode)
Save将XML文档保存到指定的文件

🏳️‍🌈生成XML文件

Unity引擎中如何生成本地XML数据步骤如下:

示例代码

using UnityEngine;
using UnityEngine.UI;
using System.Xml;

public class DataTest : MonoBehaviour
{
    public Button b1;
    void Start()
    {
        b1.onClick.AddListener(CreateXML);
    }
    public void CreateXML()
    {
        //创建xml文件
        XmlDocument doc = new XmlDocument();
        //创建xml头
        XmlNode xmlNode = doc.CreateXmlDeclaration("1.0", "utf-8", null);
        //添加xml头
        doc.AppendChild(xmlNode);
        //创建xml根节点
        XmlElement root = doc.CreateElement("users");
        //添加xml根节点
        doc.AppendChild(root);

        //通过XmlNode创建根节点的子节点
        XmlNode xn_enement = doc.CreateNode(XmlNodeType.Element, "Name", null);
        XmlNode xn_enement2 = doc.CreateNode(XmlNodeType.Element, "Age", null);
        //设置子节点的值
        xn_enement.InnerText = "张三";
        xn_enement2.InnerText = "18";
        //创建属性
        XmlAttribute xa = doc.CreateAttribute("name");
        XmlAttribute xa2 = doc.CreateAttribute("age");
        //设置属性值
        xa.Value = "12345";
        xa2.Value = "";
        //获取元素的document
        XmlDocument xd = xn_enement.OwnerDocument;
        //设置元素属性
        xn_enement.Attributes.SetNamedItem(xa);
        xn_enement2.Attributes.SetNamedItem(xa2);


        //通过XmlElement再创建一个根节点的子节点
        XmlElement element = doc.CreateElement("sex");
        element.SetAttribute("性别", "");
        element.InnerText = "男";

        //添加到子节点到root结点
        root.AppendChild(xn_enement);
        root.AppendChild(xn_enement2);
        root.AppendChild(element);

        //保存xml
        doc.Save(Application.dataPath+"/test.xml");  
    }
}

运行结果:


上述示例代码中姓名name和年龄age是通过XmlNode创建节点的方式添加的数据

性别sex则是通过XmlElement创建生成的数据,从结果来看添加的数据都一样

实际创建的时候要根据节点和元素的不同严格创建,这里只是提供了一个示例方法!


🏳️‍🌈读取Xml文件并添加数据

上面既然说了怎样生成一个xml,那就再来写一个怎样读取和添加数据的示例吧

上代码:

    void AddXMLData()
    {
        string path = Application.dataPath + "/test3.xml";
        if (File.Exists(path))
        {
            XmlDocument xml = new XmlDocument();
            xml.Load(path);
            XmlNode root = xml.SelectSingleNode("users");

            XmlElement elementChild1 = xml.CreateElement("Hobby");
            elementChild1.SetAttribute("爱好", "");
            elementChild1.InnerText = "睡大觉";

            //把节点添加至xml中,注意他们之间的先后顺序,这是生成XML文件的顺序
            root.AppendChild(elementChild1);
            //最后保存文件
            xml.Save(path);
        }
    }

加载xml文件很简单,找到对应的XML文件路径,使用xml.Load进行加载即可!

然后再通过找到节点,按照层级添加数据即可!


🎥Json

本文说的三种数据存储方式,Json其实是最常用也是目前用的比较多的一种,超轻量级,可便捷性使用

平时用到比较多的都是解析Json和往Json中添加数据、修改数据等等

下面一起来看一下具体怎样使用Json保存数据!

🏁Json简介

JSON(javascript Object Notation, JS 对象标记) 是一种轻量级的数据交换格式。
它基于 ECMAScript (w3c制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。

在Unity中大致有三种使用Json的方式

分别是使用类库的两种:System.Json(便于JSON⽣成) 和 LitJson(便于JSON解析)

还有一种是 UnityEngine.JsonUtility

其中前两种都需要将System.Json.dllLitJson.dll两个dll文件放到Unity的Plugins文件夹中才能使用相应的命名空间和方法
UnityEngine.JsonUtility则可以直接使用其中的方法


🏁Json语法规则

✨数据都放置到一个大括号里
✨一对对的数据放到大括号里
✨一个个的数据放到中括号里
✨一个大括号或一个中括号都可以表示一个值
✨数据与数据之间用逗号分隔
✨Key必须要用引号引起来
✨Value如果是字符串要用引号引起来
✨最后一个数据后面不要加逗号
✨数据保存在键值对中

Json语法示例:

{"students":[
	{
		"name":"albert",
		"age":19,
		"sex":"M"
	},
	{
		"name":"mary",
		"age":11,
		"sex":"W"
	}
	]
}

解析成实体类后:

public class StudentsItem
{
    public string name { get; set; }
    public int age { get; set; }
    public string sex { get; set; }
}
 
public class Root
{
    public List <StudentsItem > students { get; set; }
}

由于Json对字符串的格式非常严格,输入一个字符错误都不行,所以我们可以使用相关的Json转换网站进行格式转换

https://www.json.cn/json/json2csharp.html这个网站就可以实现JSON数据转实体的功能

这样我们就可以省去一些麻烦事了!


📒System.Json

先来说一下 System.Json的基本用法

System.Json是一种类库,当我们在Unity中导入System.Json.dll文件后就可以使用System.Json.dll json命名空间

可以用到的类:JsonArray、JsonObject、JsonPrimitive、JsonValue。枚举:JsonType

具体操作,在Unity中新建一个Plugins文件夹,然后将dll文件放入即可

说明
JsonArrayJsonArray 是0个或更多的 JsonObject 对象的有序序列
JsonObjectJsonObject 是一个无序的0个或更多的 键/值对 的集合
JsonValue具体的Value值

生成Json的示例方法:
下面来对Unity中的Transform面板做一个示例生成对应的Json文件

using System.Json;
using UnityEngine;

public class JsonTest : MonoBehaviour
{
    void Start()
    {
        //创建⼀个JSON对象,相当于⼀个⼤括号
        JsonObject jsonTransform = new JsonObject();

        //创建⼀个JSON值对象,存储⼀个Value
        JsonValue jsonPosition = "10,20,30";
        //JSON对象,也就是⼤括号,添加⼀个key:value
        jsonTransform.Add("position", jsonPosition);
        //打印结果
        Debug.Log(jsonTransform.ToString());

        //定义⼀个值数组,⽤来存储,中括号中的⼀个个的值
        JsonValue[] rotationXYZ = new JsonValue[] { 20, 30, 40 };
        //将这个数组中的⼀个个的值放到JsonArray数组对象中
        JsonArray jsonRotation = new JsonArray(rotationXYZ);
        //⼀个JsonArray对象,也可以是⼀个Value,
        //所以可以⽤jsonTransform来Add
        jsonTransform.Add("rotation", jsonRotation);
        //打印结果
        Debug.Log(jsonTransform);

        JsonObject x = new JsonObject();
        x.Add("x", 10);
        JsonObject y = new JsonObject();
        y.Add("y", 20);
        JsonObject z = new JsonObject();
        z.Add("z", 30);
        //实例⼀个jsonValues数组(所有类型都可以转换成jsonValue)
        JsonValue[] scaleXYZ = new JsonValue[] { x, y, z };
        //将实例好了的数组,添加到jsonArray对象中,形成⼀个jsonArray对象
        //作⽤在于给这个整体,添加⼀个中括号[]
        JsonArray jsonScale = new JsonArray(scaleXYZ);
        //将这个整体,放⼊到jsonTransform中
        jsonTransform.Add("scale", jsonScale);
        //打印结果
        Debug.Log(jsonTransform);
    }
}

打印结果:


📒LitJson

ListJsonSystem.Json一样,都需要先在Unity的Plugins文件夹导入LitJson.dll文件才可以使用其中的API方法

常用API方法如下:

  • ✨把对象转化成 JSON格式字符串: JsonMapper.ToJson
  • ✨把JSON格式字符串转化成对象: JsonMapper.ToObject
  • ✨把JSON格式字符串转化成指定类的对象:JsonMapper.ToObject

📒UnityEngine.JsonUtility

JsonUtility 是Unity内置的用于解析Json的方法,跟LitJson用法很像

而且不需要导入dll文件就可以直接使用,应用于平时一些小项目开发使用到Json的时候完全可以够用啦!

下面来说一下JsonUtility的几种常用方法


🏴生成Json文件

我们写一个字段类Person,类里面有string类型的“Name”和int类型的“Age”

using System.IO;
using UnityEngine;

[System.Serializable]
class Person
{
    public string Name;
    public int Age;
}
[System.Serializable]
class Data
{
    public Person[] Person;
}
public class NewBehaviourScript : MonoBehaviour
{
    void Start()
    {
        WriteData();
    }

    //写数据
    public void WriteData()
    {
        //新建一个数据类
        Data m_Data = new Data();
        //新建一个字段类 进行赋值
        m_Data.Person = new Person[3];
        for (int i = 0; i < 3; i++)
        {
            Person m_Person = new Person();
            m_Person.Name = "User" + i;
            m_Person.Age = 20 + i;
            m_Data.Person[i] = m_Person;
        }

        //将数据转成json
        string js = JsonUtility.ToJson(m_Data);
        //获取到项目路径
        string fileUrl = Application.dataPath + "\\\\jsonInfo.txt";

        //打开或者新建文档
        using (StreamWriter sw = new StreamWriter(fileUrl))
        {
            //保存数据
            sw.WriteLine(js);
            //关闭文档
            sw.Close();
            sw.Dispose();
        }
    }
}

生成的Json内容如下:

示例代码里面新建了两个数据实体类,一个Data 一个Person

它们都有特性:[System.Serializable],也就是序列化,只有加上这个特性,类里面的数据才能正常的转成Json数据。


🏴解析Json文件

先读取Json文件,使用IO命名空间下的File类的OpenText()函数进行读取

然后使用JsonUtility.FromJson进行解析

using System.IO;
using UnityEngine;

[System.Serializable]
class Person
{
    public string Name;
    public int Age;
}
[System.Serializable]
class Data
{
    public Person[] Person;
}
public class NewBehaviourScript : MonoBehaviour
{
    void Start()
    {
        string jsonData = ReadData();
        Data m_PersonData = JsonUtility.FromJson<Data>(jsonData);
        foreach (Person item in m_PersonData.Person)
        {
            Debug.Log(item.Name);
            Debug.Log(item.Age);
        }
    }

    //读取文件
    public string ReadData()
    {
        //string类型的数据常量
        string readData;
        //获取到路径
        string fileUrl = Application.dataPath + "\\\\jsonInfo.json";
        //读取文件
        using (StreamReader sr = File.OpenText(fileUrl))
        {
            //数据保存
            readData = sr.ReadToEnd();
            sr.Close();
        }
        //返回数据
        return readData;
    }
}

打印效果如下:


💬总结