不同于unity自带的PlayerPrefs的字典式存储,本文主要说明三种文件存储的具体实现方式(项目原型基于siki案例–存档与读档,类似于打砖块的小游戏),即:二进制方法、XML以及JSON。

三种存储方式的对比

一、二进制方式存储
存储简单,但基本没有可读性。
二、XML
可读性强,但文件庞大,冗余信息多。
三、JSON
数据格式比较简单,易于读写,但是不直观,可读性比XML差。

三种方式存储的预先准备

首先得创建一个Save类存储相关数据并标记为可序列化,本例具体代码如下:
(新建一个C#脚本,将继承类删除即可开始编写Save类,Save类用于存储需要存储的数据)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;[System.Serializable]
public class Save
{public List<int> activeMonsterPosition = new List<int>();public List<int> activeMonsterType = new List<int>();public int shootNum;public int score;
}

一、二进制方式的存档与读档

需要添加两个命名空间
1、using System.IO; //用于文件的读写
2、using System.Runtime.Serialization.Formatters.Binary; //用于创建二进制格式化程序

存档代码如下:

private void SaveByBin(){//创建存储类对象Save save = CreateSaveGo();//创建二进制格式化程序BinaryFormatter binaryFormatter = new BinaryFormatter();//创建文件流(create参数为存储路径,注意路径前的"/"以及标明文件名称和格式)FileStream fileStream = File.Create(Application.dataPath + "/StreamingFile" + "/byBin.txt");//用二进制格式化程序的序列化方法来序列化save对象 binaryFormatter.Serialize(fileStream, save);//关闭文件流fileStream.Close();}

读档代码如下:

private void LoadByBin(){if (File.Exists(Application.dataPath + "/StreamingFile" + "/byBin.txt")) //检测是否存在读档信息{//创建二进制格式化程序BinaryFormatter binaryFormatter = new BinaryFormatter();//创建文件流打开读档信息FileStream fileStream = File.Open(Application.dataPath + "/StreamingFile" + "/byBin.txt", FileMode.Open);//调用二进制格式化程序的反序列化方法,将文件流转化为Save对象Save save = (Save)binaryFormatter.Deserialize(fileStream); //返回值为object类型,需要强制转换为需要的类型//关闭文件流fileStream.Close();//将读取到的游戏属性设置为游戏当前属性(根据游戏需要自行编写)SetGame(save);}}

二、JSON方式的存档与读档

需要添加两个命名空间
1、using System.IO; //用于文件的读写
2、using LitJson;//用于json数据的转换(需要自行导入LitJson.dll文件)

存档代码如下:

 private void SaveByJson(){//保存当前游戏状态,创建save对象(CreateSaveGo函数根据保存数据需要编写)Save save = CreateSaveGo();//保存文件路径(美化代码)string filePath = Application.dataPath + "/StreamingFile" + "/byJson.json";//文件类型可以时.json也可以是.txt//通过JsonMapper.ToJson方法将save对象中的数据转化为json字符串保存下来string saveJsonStr = JsonMapper.ToJson(save);//using LitJson;//创建StreamWriter写入流(注意需要一个string参数代表路径)StreamWriter streamWriter = new StreamWriter(filePath);//将转化后的字符串写入目标文件streamWriter.Write(saveJsonStr);//关闭StreamWriterstreamWriter.Close();}

读档代码如下:

读档代码逻辑就是存档的反向逻辑。

 private void LoadByJson(){ //string保存路径(美化代码)string filePath = Application.dataPath + "/StreamingFile" + "/byJson.json";//创建文件读取流(注意new对象时需要string类型参数代表路径)StreamReader streamReader = new StreamReader(filePath);//读取文件中所有的字符串(ReadToEnd代表读取到最后,即读取所有)string jsonStr = streamReader.ReadToEnd();//将读取到的字符串通过JsonMapper.ToObject转换为Save类型的对象(JsonMapper.ToObject<类型>(路径);)Save save = JsonMapper.ToObject<Save>(jsonStr);//using LitJson;//设置游戏状态,根据游戏需要自行编写SetGame(save);}

三、XML方式的存档与读档

需要添加两个命名空间
1、using System.IO; //用于文件的读写
2、using System.Xml; //用于创建XML文档

存档代码如下:

xml虽然有系统自带的类库,但是所有的结点需要自己添加,相比其它两种方法要麻烦,但过程逻辑不复杂,了解自己编写的Save类即可轻松编写。
总体思路是 XmlDocument ( root ( target( …… ) – shootNum – score ) ) 【括号代表层级关系,"–"代表同级】

 private void SaveByXml(){//保存当前游戏状态,创建save对象(CreateSaveGo函数根据保存数据需要编写)Save save = CreateSaveGo();//保存文件路径(美化代码)string filePath = Application.dataPath + "/StreamingFile" + "/byXml.txt";//总思路:XmlDocument (    root (  target(  ……  ) -- shootNum -- score  )   )//括号代表层级关系,"--"代表同级//创建Xml文档XmlDocument xmlDocument = new XmlDocument();//创建xml根节点XmlElement root = xmlDocument.CreateElement("save");//设置根结点的值(名字的名称 ,名字)root.SetAttribute("name", "saveFile1");//创建xml元素(每个元素都包含名称 和 内部包含的值)XmlElement target;XmlElement targetPosition;XmlElement monsterType;//循环赋值for (int i = 0; i < save.activeMonsterPosition.Count; i++){//设置xml元素的名称target = xmlDocument.CreateElement("target");targetPosition = xmlDocument.CreateElement("targetPosition");monsterType = xmlDocument.CreateElement("monsterType");//设置xml元素内部包含的值(即存储的字符串)targetPosition.InnerText = save.activeMonsterPosition[i].ToString();monsterType.InnerText = save.activeMonsterType[i].ToString();//设置层级关系(root -> target -> ( targetPosition -- monsterType ) )root.AppendChild(target);target.AppendChild(targetPosition);target.AppendChild(monsterType);}//创建xml元素并设置名称XmlElement shootNum = xmlDocument.CreateElement("shootNum");XmlElement score = xmlDocument.CreateElement("score");//设置xml元素内部包含的值(即存储的字符串)shootNum.InnerText = save.shootNum.ToString();score.InnerText = save.score.ToString();//设置层级关系(xmlDocument -> root -> ( shootNum -- score ))root.AppendChild(shootNum);root.AppendChild(score);xmlDocument.AppendChild(root);//将xml文档保存到指定路径xmlDocument.Save(filePath);}

读档代码如下:

总体思路: XmlDocument -> XmlNodeList -> XmlNode ( -> XmlNode .ChildNodes[……]) -> InnerText

  private void LoadByXml(){//保存文件路径(美化代码)string filePath = Application.dataPath + "/StreamingFile" + "/byXml.txt";//当保存文件存在时进行读档if (File.Exists(filePath)){//创建Save保存类对象Save save = new Save();//创建xml文档XmlDocument xmlDocument = new XmlDocument();//加载指定路径的xml文档xmlDocument.Load(filePath);//通过结点名来获取结点,返回值为XmlNodeList类型(存储XmlNode的List)XmlNodeList targets = xmlDocument.GetElementsByTagName("target");//当存在target时进行遍历if (targets.Count != 0){//foreach遍历获得的list -- targetsforeach (XmlNode target in targets){//获得list中的结点(对应位置参考存储时的位置)XmlNode targetPosition = target.ChildNodes[0];//直接获得该结点的innerText值(注意转化类型)int targetPositionIndex = int.Parse(targetPosition.InnerText);//给save对象赋值save.activeMonsterPosition.Add(targetPositionIndex);//获得list中的结点(对应位置参考存储时的位置)XmlNode monsterType = target.ChildNodes[1];//直接获得该结点的innerText值(注意转化类型)int monsterTypeIndex = int.Parse(monsterType.InnerText);//给save对象赋值save.activeMonsterType.Add(monsterTypeIndex);}}//通过结点名来获取结点,返回值为XmlNodeList类型(存储XmlNode的List)XmlNodeList shootNumCount = xmlDocument.GetElementsByTagName("shootNum");//注意当XmlNodeList中的XmlNode没有子节点的时候可以直接获得XmlNode的InnerTextint shootNum = int.Parse(shootNumCount[0].InnerText);//给save对象赋值save.shootNum = shootNum;//通过结点名来获取结点,返回值为XmlNodeList类型(存储XmlNode的List)XmlNodeList scoreCount = xmlDocument.GetElementsByTagName("score");//注意当XmlNodeList中的XmlNode没有子节点的时候可以直接获得XmlNode的InnerTextint score = int.Parse(scoreCount[0].InnerText);//给save对象赋值save.score = score;//将读取到的游戏属性设置为游戏当前属性(根据游戏需要自行编写)SetGame(save);}}

本例中的CreateSaveGo()函数和SetGame()函数

CreateSaveGo():

   private Save CreateSaveGo(){Save save = new Save();//遍历每一个目前存活的目标,逐个保存foreach (GameObject targetGo in targetGos){TargetManager targetManager = targetGo.GetComponent<TargetManager>();if (targetManager.activeMonster != null){save.activeMonsterPosition.Add(targetManager.targetPosition);int type = targetManager.activeMonster.GetComponent<MonsterManager>().monsterType;save.activeMonsterType.Add(type);}}//保存UI属性save.shootNum = UIManager._instance.shootNum;save.score = UIManager._instance.score;return save;}

SetGame():

    private void SetGame(Save save){foreach (GameObject target in targetGos){target.GetComponent<TargetManager>().UpdateMonster();//先将所有怪物清空}for (int i = 0; i < save.activeMonsterPosition.Count; i++){int position = save.activeMonsterPosition[i];int type = save.activeMonsterType[i];targetGos[position].GetComponent<TargetManager>().ActiveMonsterByType(type);//激活指定位置的怪物}//设置UIUIManager._instance.shootNum = save.shootNum;UIManager._instance.score = save.score;DePause();//取消暂停状态、关闭菜单}

unity -- 存档与读档相关推荐

  1. Unity游戏存档与读档

    目前unity常见存档和读档有几种方式,也就是常见的存储数据的方式(注意存档和读档都是针对单机游戏而言的,角色信息,道具信息,关卡情况等) Unity存档的方式大概分为这两大类 图片来源自siki学院 ...

  2. Unity中采用JSON进行存档和读档

    在利用JSON做存档和读档之前,首先要在Assets导入一个脚本!这个脚本就是LitJson.dll 然后在Unity中首先创建一个Save脚本,用于保存游戏中相关的信息,在这里我存储的是游戏中怪物的 ...

  3. C++ 关于存档与读档

    c++可以用来制作游戏.可是,如果制作的游戏不能存档,那就特别让人心疼了.这种的游戏通常都是辛辛苦苦玩了半天,好不容易打出的记录,程序重启后,一夜回到解放前. 看着宝贵的血汗数据就这样变为0,小凤我决 ...

  4. SaveLoad--Unity存档读档的学习总结

    存档与读档功能 举例: 传统RPG游戏(仙剑.空之轨迹): 1.角色信息(生命值,等级) 2.道具信息(装备,药品) 3.场景信息(场景名称.角色坐标) 4.事件信息(任务相关) 关卡类游戏:关卡的通 ...

  5. Unity_二进制,Jason,XML存档读档

    创建一个类Save 用来保存游戏的信息,以便于存档 Save.cs的代码 using System.Collections; using System.Collections.Generic; usi ...

  6. 正版七日杀服务器存档,七日杀网吧怎么存档 七日杀网吧存档读档方法介绍-游侠网...

    七日杀的电脑要求配置虽然不是特别高,但是相对于很多玩家的电脑来说还是一个不小的负担的,所以很多玩家会选择去网吧游玩,但是很多玩家发现网吧非主机玩家的人物数据重进总是清零.所以今天小编就为大家带来了便是 ...

  7. 游戏服务器之存档读档

    设计上: (1)存档方式 定时器在一定范围的分钟内随机存档一次,为了避免集中式存档 第一次需要全部存档一次,因为需要存档版本字段 分标签实时存档设置了标签的数据,减少每次存档数据 (2)压缩处理 档案 ...

  8. [虚幻引擎][UE][UE5]简单的游戏读档存档

    [虚幻引擎][UE][UE5]简单的游戏读档存档

  9. Python 名片管理系统(文件版,可存档读档)

    Python 名片管理系统(文件版,可存档读档) 相比于函数版的程序,文件版增加了存档读档操作 函数版的可以参考Python名片管理系统(列表.字典和函数的综合应用) 以下是新增部分的代码(不包括调用 ...

  10. [Unity存档系统]简单介绍Unity常见存档系统二JSON以及使用方法

    学习目标: 如果你和我同样苦恼于游戏相关的数据怎么存储与读取,那么不妨看看这个up主有关Unity存档系统的教程.[Unity] 存档系统 Part 1 | PlayerPrefs | Unity初学 ...

最新文章

  1. 光热发电未来或成长为南非电力供应市场的主力军
  2. apache配置证书后 tomcat无法访问_给你的项目配置个https吧
  3. 使用git 添加远程仓库 或者 从远程仓库克隆的两种实现
  4. (pytorch-深度学习系列)卷积神经网络LeNet-学习笔记
  5. html5 客户端数据缓存机制,深入理解HTML5离线缓存机制
  6. 利用汇编与机器码定位崩溃点
  7. python使用redis_使用Python构建您的第一个Redis Hello World应用程序
  8. centos7 mysql8 主从_CentOS7开启MySQL8主从备份、每日定时全量备份(推荐)
  9. 一个人是否靠谱,闭环很重要(有深度)
  10. vulntarget-a靶场的学习思考
  11. 【高登世德:为资产证券化引入区块链技术】GBCAX
  12. 支付宝20积分兑换15天会员
  13. linux人脸识别终端是什么意思,瑞芯微如何看待天波首发得RV1109 Linux人脸识别终端...
  14. 天锋w2019_华强北神机天锋W2019堪比真机,一不小心就被套路
  15. 基因-药物相互作用数据库 DGIdb 介绍
  16. 二层网络的未来?starkgate 带你体验二层桥接
  17. 通信原理与MATLAB(十三):AMI的编解码
  18. iPhone14 3D模型免费下载
  19. 设置HP 1022n打印机为网络打印机的经验教训
  20. 趣味编程Python之折纸去月球!!!

热门文章

  1. 只需5秒,赶走阴冷寒风,迎来温暖热浪,云米对流电暖器体验
  2. 【无代码爬虫】web scraper 之 采集单个内容
  3. STM32L431 I2S/IIS slaver使用
  4. Deprecated注解
  5. 12306订票候补是个坑_12306候补购票好几天了都没兑现成功是不是凉凉了?
  6. 京东朱健:聊聊京东广告系统的数据库选型
  7. 小程序 全屏滑动【亲测有效】
  8. QLineEdit光标问题
  9. 吞噬星空java_(完)Java基础练习题:题目:将一个正整数分解质因数。例如:输入90,打印出90=2*3*3*5。 - 菜鸟头头...
  10. LOW逼三人组(二)----选择排序算法