Unity 序列化和反序列化的三种存储方式

使用序列化存储游戏数据,方便将对象从一个地方移动到另一个地方(转移文件再反序列化读取)使游戏数据不容易被直接篡改。

二进制方法:简单,但可读性差。
XML:可读性强,但是文件庞大,冗余信息多。
JSON:数据格式比较简单,易于读写,但是不直观,可读性比XML差。

首先我们创建一个名为Save的脚本:

using UnityEngine;
using System.Collections;

[System.Serializable]//序列化
public class Save{
	public int score = 0;
}

其次我们创建一个名为GameManager的脚本来读取和修改数据:

using UnityEngine;
using System.Collections;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Collections.Generic;

public class GameManager : MonoBehaviour {
	private int localScore;
	private Save CreateSaveGO(){
		//创建Save对象并存储当前游戏状态信息
		Save save = new Save();
		//把score保存在Save对象中
		save.score = localScore;
		//返回该Save对象
		return Save;
	}
	//通过读档信息加载游戏状态
	private void SetGame(Save save){
		//读取游戏状态信息
		localScore = save.score;
	}		
}

最后我们使用三种存储方法对游戏进行保存与加载。

一、二进制方法:存档与读档

命名空间:
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

private void SaveByBin(){
	//序列化过程(将Save对象转换为字节流)
	//创建Save对象并保存当前游戏状态
	Save save = CreateSaveGO();
	//创建一个二进制格式化程序
	BinaryFormatter bf = new BinaryFormatter();
	//创建一个文件流(其中"/StreamingFile"指的是在Unity Project下的Assets资源文件夹中创建的StreamingFile文件夹)
	FileStream fileStream = File.Create(Application.dataPath + "/StreamingFile" + "/byBin.txt");
	//用二进制格式化程序的序列化方法来序列化Save对象,参数:创建的文件流和需要序列化的对象
	bf.Serialize(fileStream,save);
	//关闭流
	fileStream.Close();
	
	//如果文件存在,则显示保存成功
	if(File.Exists(Application.dataPath + "/StreamingFile" + "/byBin.txt"))
	{
		Debug.Log("保存成功");
	}
}

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);
		Debug.Log("加载成功");
	}else{
		Debug.Log("存档文件不存在");
	}
}

二、XML:存档与读档

命名空间:
using System.Xml;

private void SaveByXml(){
	Save save = CreatSaveGO();
	//创建XML文件的存储路径(其中"/StreamingFile"指的是在Unity Project下的Assets资源文件夹中创建的StreamingFile文件夹)
	string filePath = Application.dataPath + "/StreamingFile" + "/byXML.txt";
	//创建XML文档
	XmlDocument xmlDoc = new XmlDocument();
	//创建根节点,即最上层节点
	XmlElement root = xmlDoc.CreateElement("save");
	//设置根节点中的值
	root.SetAttribute("name","saveFile1");
	
	//创建XmlElement
	XmlElement score = xmlDoc.CreateElement("score");
	//设置InnerText值并设置层级关系(xmlDoc -- root -- score)
	score.InnerText = save.score.ToString();
	root.AppendChild(score);
	xmlDoc.AppendChild(root);
	xmlDoc.Save(filePath);
	
	if(File.Exists(Application.dataPath + "/StreamingFile" + "/byXML.txt"))
		{
			Debug.Log("保存成功");
		}
}

private void LoadByXml(){
	string filePath = Application.dataPath + "/StreamingFile" + "/byXML.txt";
	if(File.Exists(filePath))){
		Save save =new Save();
		//加载XML文档
		XmlDocument xmlDoc = new XmlDocument();
		xmlDoc.Load(filePath);
		
		//通过节点名称来获取元素,结果为XmlNodeList类型
		XmlNodeList score = xmlDoc.GetElementsByTagName("score");
		int scoreCount = int.Parse(score[0].InnerText);
		save.score = scoreCount;
		
		SetGame(save);
		Debug.Log("加载成功");
	}else{
		Debug.Log("存档文件不存在");
	}
}

三、Json:存档与读档

命名空间:
using LitJson;

private void SaveByJson(){
	Save save = CreateSave();
	//"/StreamingFile"指的是在Unity Project下的Assets资源文件夹中创建的StreamingFile文件夹,存储的文件可以是json格式也可是txt格式
	string filePath = Application.dataPath + "/StreamingFile" + "/byJson.json";
	//利用JsonMapper将save对象转换为Json格式的字符串
	string saveJsonStr = JsonMapper.ToJson(save);
	//将字符串写入到文件中
	//创建一个StreamWriter,并将字符串写入文件中
	StreamWriter sw = new StreamWriter(filePath);
	sw.Write(saveJsonStr);
	//关闭StreamWrite
	sw.Close();
	Debug.Log("保存成功");
}

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);
		SetGame(save);
		Debug.Log("加载成功");
	}else{
		Debug.Log("存档文件不存在");
	}
}

备注:利用Json对数据进行存档读档前需要将Json的库放进Unity Project下的Assets资源文件夹中。

拓展:

一、Using 自动释放流
除了用Close关闭流文件外可以用using自动释放流:

try {
	BinaryFormatter bf=new BinaryFormatter();
	using(FileStream fs=File.Create(Application.persistentDataPath+"/GameData.data")){
			//使用using可以自动释放流
			//将类的数据序列化写进本地
		}
	} catch (System.Exception ex) {
			Debug.Log (ex.Message);
	}

二、PlayerPrefs 数据持久化
PlayerPrefs用于本地持久化保存与读取的类,工作原理很简单,以键值对的形式将数据保存在文件中,然后程序可以根据这个名称取出上次保存的数值(注:数据通过键名来读取,当值不存在时,返回默认值)。

Playerprefs类支持3种数据类型的保存和读取,分别是浮点型、整型和字符串型:
PlayerPrefs.SetInt();保存整型数据
PlayerPrefs.SetFloat();保存浮点型数据
PlayerPrefs.SetString();保存字符串型数据
PlayerPrefs.GetInt();读取整型数据
PlayerPrefs.GetFloat();读取浮点型数据
PlayerPrefs.GetString();读取字符串型数据

例子(对游戏内背景音乐是否开启进行存储):

public Toggle musicToggle;
public AudioSource musicAudio;

private void Awake(){
	if(PlayerPrefs.HasKey("MusicOn")){
		if(PlayerPrefs.GetInt("MusicOn") == 1){
			musicToggle.isOn = true;
			musicAudio.enable = true;
		}else{
			musicToggle.isOn = false;
			musicAudio.enable = false;
		}
	}else{
		musicToggle.isOn = true;
		musicAudio.enable = true;
	}
}
public void MusicSwitch(){
//通过判断单选框是否被勾选上,从而决定是否播放背景音乐
	if(musicToggle.isOn == false){
		musicAudio.enable == false;
		//保存音乐开关的状态,0代表关闭状态
		PlayerPrefs.SetInt("MusicOn",0);
	}else{
		musicAudio.enable = true;
		PlayerPrefs.SetInt("MusicOn",1);
	}
	PlayerPrefs.Save();//对数据进行存储
}
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值