Unity C#保存数据与读取数据

Unity存储简介

Unity保存数据分为二进制、Json、Xml、Excel等方式,还有一个Unity缓存方法。
将游戏数据存储起来,实现读档功能
数据保存时和读取时需要设专门的类
对类里面的变量进行读取和赋值达到读档、存档功能。

Unity缓存方法

Unity通过PlayerPrefs,通过键值对的方式存储,只能存储只能存储int,float,string这三种数据类型,扩展方式强
存储时:

	 if (MusicToggle.isOn==false)
      {
         MusicAudioSource.enabled = false;
         PlayerPrefs.SetInt("MusicOn",0);
      }
      else
      {
         MusicAudioSource.enabled = true;
         PlayerPrefs.SetInt("MusicOn",1);
      }
      PlayerPrefs.Save();

读取时:

	  if (PlayerPrefs.HasKey("MusicOn"))
      {
         if (PlayerPrefs.GetInt("MusicOn")==1)
         {
            MusicToggle.isOn = true;
         }
         else
         {
            MusicToggle.isOn = false;
         }
      }

具体在参考文档:
https://docs.unity.cn/cn/current/ScriptReference/PlayerPrefs.html

游戏数据存储

首先,创建一个类去存储和读取数据

public class Save
{
    public List<int> livingTargetPositions = new List<int>();
    public List<int> livingMonsterTypes = new List<int>();
    public int shootTimes = 0;
    public int score = 0;
}

将要保存的游戏数据存进类中

 	private Save CreatSaveGO()
   {
      Save save = new Save();
      foreach (var target in targets)
      {
         TargetManager targetManager = target.GetComponent<TargetManager>();
         if (targetManager.activeMonster != null)
         {
            save.livingTargetPositions.Add(targetManager.targetPosition);
            int type = targetManager.activeMonster.GetComponent<MonsterManager>().monsterType;
            save.livingMonsterTypes.Add(type);
         }
      }
      save.shootTimes = UIManager._instance.shoottimes;
      save.score = UIManager._instance.score;
      return save;
   }

二进制方法

游戏管理的脚本添加引用

using System.Runtime.Serialization.Formatters.Binary;
C#自带的,将数据以二进制的格式存储

	private void SaveByBin()
   {
      //序列化过程,创建Save对象并保存当前游戏状态
      Save save = CreatSaveGO();
      //创建一个二进制格式化程序
      BinaryFormatter bf = new BinaryFormatter();
      //创建一个文件流
      FileStream fileStream = File.Create(Application.dataPath + "/StreamingFile" + "/ByBin.txt");//地址
      //用二进制格式化程序的序列化方法来序列化Save对象,参数:创建的文件流和需要序列化的对象
      bf.Serialize(fileStream,save);
      //关闭
      fileStream.Close();
      
      if (File.Exists(Application.dataPath + "/StreamingFile" + "/ByBin.txt"))
      {
         UIManager._instance.ShowMessage("保存成功!");
      }
   }
	private void LoadByBin()
   {
      if (File.Exists(Application.dataPath + "/StreamingFile" + "/ByBin.txt"))
      {
         //反序列化过程
         //创建一个二进制格式化程序
         BinaryFormatter bf = new BinaryFormatter();
         //打开一个文件流
         FileStream fileStream = File.Open(Application.dataPath + "/StreamingFile" + "/ByBin.txt",FileMode.Open);
         //调用格式化程序的反序列化方法,将文件流转换为一个Save对象
         Save save = (Save) bf.Deserialize(fileStream);
         //关闭文件流
         fileStream.Close();
         
         SetGame(save);
         UIManager._instance.ShowMessage("");
      }
      else
      {
         UIManager._instance.ShowMessage("存档文件不存在!");
      }
    
  }

Json存储

Json方式存储,需要先在NuGet包获取LitJson包
Rider找NuGet
获取之后
获取之后到工程文件里找
找到对应的.net的dll库
根据自己工程的PlayerSetting选择
.net的版本
dll文件
将这个文件拖进工程里
然后开始在脚本里添加引用:using LitJson;

	private void SaveByJson()
   {
      Save save = CreatSaveGO();
      string filePath = Application.dataPath + "/StreamingFile" + "/ByJson.json";
      //利用JsonMapper将save对象转换为Json格式的字符串
      string saveJsonStr = JsonMapper.ToJson(save);
      //将这个字符串写入到文件中
      //创建一个StreamingWriter
      StreamWriter sw = new StreamWriter(filePath);
      sw.Write(saveJsonStr);
      //关闭StreamWriter
      sw.Close();
      
      UIManager._instance.ShowMessage("保存成功!");
   }

关于第三方库

LitJson默认是Unicode编码方式,所以存储中文是\uXXXX类型的
这个函数的作用是把正则表达式表示的字符串转换成非正则表达式的字符串

所以,如果存储的数据包含中文,则需要添加引用:using System.Text.RegularExpressions;
string saveJsonStr = JsonMapper.ToJson(save); 改为 string saveJsonStr=Regex.Unescape(JsonMapper.ToJson(save));

   private void LoadByJson()
   {
      string filePath = Application.dataPath + "/StreamingFile" + "/ByJson.json";
      if (File.Exists(filePath))
      {
         //创建一个StreamReader,用来读取流
         StreamReader sr = new StreamReader(filePath);
         //将读取到的流赋值给jsonstr
         string jsonStr = sr.ReadToEnd();
         //关闭
         sr.Close();
         
         //将字符串jsonStr转换为Save对象
         Save save = JsonMapper.ToObject<Save>(jsonStr);//jsonStr为文件的内容转换成了字符串,这里需要将字符串转换成目标对象
         
         SetGame(save);
         UIManager._instance.ShowMessage("");
      }
      else
      {
         UIManager._instance.ShowMessage("存档文件不存在!");
      }
   }

File.Exists(filePath) 用来判断的文件是否存在

Xml存储

Xml存储运用的是C#自带的库
添加引用using System.Xml;
Xml文件创建方式不像以上方法简便,需要手动添加根节点、子节点
例子中每个节点作为一个target进行存储

	private void SaveByXml()
   {
      Save save = CreatSaveGO();
      //创建XML文件的存储路径
      string filePath = Application.dataPath + "/StreamingFile" + "/ByXml.txt";
      //创建XML文档
      XmlDocument xmlDocument = new XmlDocument();
      //创建根节点,即最上层节点
      XmlElement root = xmlDocument.CreateElement("save");
      //设置根节点的值
      root.SetAttribute("name", "saveFile1");
      
      //创建XmlElement
      XmlElement target;
      XmlElement targetPosition;
      XmlElement monsterType;
      
      //创建save中存储的数据,将数据转换成Xml格式
      for (int i = 0; i < save.livingTargetPositions.Count; i++)
      {
         target = xmlDocument.CreateElement("target");
         targetPosition = xmlDocument.CreateElement("targetPosition");
         targetPosition.InnerText = save.livingTargetPositions[i].ToString();
         monsterType = xmlDocument.CreateElement("monsterType");
         monsterType.InnerText = save.livingMonsterTypes[i].ToString();
         
         //设置节点间的层级关系 root -- target -- (targetPosition, monsterType)
         target.AppendChild(targetPosition);
         target.AppendChild(monsterType);
         root.AppendChild(target);
      }

      XmlElement shootTimes = xmlDocument.CreateElement("shootTimes");
      shootTimes.InnerText = save.shootTimes.ToString();
      XmlElement score = xmlDocument.CreateElement("score");
      score.InnerText = save.score.ToString();

      root.AppendChild(shootTimes);
      root.AppendChild(score);

      xmlDocument.AppendChild(root);
      xmlDocument.Save(filePath);

      if (File.Exists(Application.dataPath + "/StreamingFile" + "/ByXml.txt"))
      {
         UIManager._instance.ShowMessage("保存成功!");
      }
   }

加载Xml文件需要考虑节点的层级关系
读取时将文件数据读成节点列表
遍历节点列表,利用层级关系将属性赋值在游戏物体上

private void LoadByXml()
   {
      string filePath = Application.dataPath + "/StreamingFile" + "/ByXml.txt";
      if (File.Exists(filePath))
      {
         Save save = new Save();
         //加载XML文档
         XmlDocument xmlDocument = new XmlDocument();
         xmlDocument.Load(filePath);
         
         //通过节点名称来获取元素,结果为XmlNodeList类型
         XmlNodeList targets = xmlDocument.GetElementsByTagName("target");
         //遍历所有的target节点,并获取子节点和子节点的InnerText
         if (targets.Count != 0)
         {
            foreach (XmlNode target in targets)
            {
               XmlNode targetPosition = target.ChildNodes[0];
               int targetPositionIndex = int.Parse(targetPosition.InnerText);
               //把获取到的值存储到save中
               save.livingTargetPositions.Add(targetPositionIndex);

               XmlNode monsterType = target.ChildNodes[1];
               int monsterTypeIndex = int.Parse(monsterType.InnerText);
               save.livingMonsterTypes.Add(monsterTypeIndex);
            }
         }

         XmlNodeList shoottimes = xmlDocument.GetElementsByTagName("shootTimes");
         int shootTimes = int.Parse(shoottimes[0].InnerText);
         save.shootTimes = shootTimes;
         
         XmlNodeList Score = xmlDocument.GetElementsByTagName("score");
         int score = int.Parse(Score[0].InnerText);
         save.score = score;
         
         SetGame(save);
         UIManager._instance.ShowMessage("");
      }
      else
      {
         UIManager._instance.ShowMessage("存档文件不存在!");
      }
   }

附上对应的Xml文件参考

<save name="saveFile1">
  <target>
    <targetPosition>1</targetPosition>
    <monsterType>1</monsterType>
  </target>
  <target>
    <targetPosition>3</targetPosition>
    <monsterType>3</monsterType>
  </target>
  <target>
    <targetPosition>5</targetPosition>
    <monsterType>3</monsterType>
  </target>
  <target>
    <targetPosition>6</targetPosition>
    <monsterType>2</monsterType>
  </target>
  <target>
    <targetPosition>7</targetPosition>
    <monsterType>3</monsterType>
  </target>
  <target>
    <targetPosition>8</targetPosition>
    <monsterType>2</monsterType>
  </target>
  <shootTimes>7</shootTimes>
  <score>4</score>
</save>

读取文件通用步骤

1、获取目标文件的存储路径,定义一个字符串记录目标文件的存储路径+/目标文件的文件名
2、判断在该路径下能否找到目标文件
3、倘若找到,创建文件流对象读取文件里的信息
4、根据文件的类型进行转换,例如:二进制文件转换成字节数组,Json文件转换成字符串
5、根据获取的数据创建对应的数据类型,进行解析存储,针对有的数据类型可以为空,需要将此类型定义为数组或列表
6、看文件是否有对应的协议,例如:文件的头部信息、数据的进制转换,再进行解析

附上解析bin文件的例子

此文件的头部信息是:1个byte存储版本号、1个int类型存储该文件里点云数据的点的个数、1个bool类型存储该文件是否包含颜色信息、接下来是点数据(3个float记录点的坐标x、y、z、3个float记录点的颜色r、g、b)

private void LoadByBin()
    {
        
        //如果该二进制文件存在的话
        if (File.Exists(Application.dataPath + "/#3_pile.bin"))
        {
            //Debug.Log("yes");
            FileStream fs = new FileStream(path, FileMode.Open);
            BinaryReader br = new BinaryReader(fs);
 
            byte b=br.ReadByte();
            int l = br.ReadInt32();
            Debug.Log(b);
            Debug.Log(l);
            bool color=br.ReadBoolean();
            for(int i=0; i < l; i++)
            {
                Point p=new Point();
                p.x=br.ReadSingle();
                p.y= br.ReadSingle();
                p.z= br.ReadSingle();
                p.r = br.ReadSingle();
                p.g = br.ReadSingle();
                p.b = br.ReadSingle();
                points.Add(p);
            }

            br.Close();
            fs.Close();
        }
        else
        {
            Debug.Log("no");
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值