Save&Load--Unity存檔讀檔的學習總結
阿新 • • 發佈:2018-12-18
存檔與讀檔功能
舉例:
傳統RPG遊戲(仙劍、空之軌跡): 1.角色資訊(生命值,等級) 2.道具資訊(裝備,藥品) 3.場景資訊(場景名稱、角色座標) 4.事件資訊(任務相關)
- 關卡類遊戲:關卡的通關情況
一些特殊的存檔機制(漫漫長夜、億萬殭屍)
Unity中使用的存檔方式
一、PlayerPrefs:資料持久化方案
原理:採用鍵值對的方式對資料進行儲存---儲存在本地檔案(不同作業系統儲存路徑不同)中,然後程式可以根據這個名稱取出上次儲存的數值)
- 儲存型別:可以儲存Int, Float, String型別的資料。
使用例子
//儲存資料: PlayerPrefs.SetInt("Index",1); PlayerPrefs.SetFloat("Height",183.5f); PlayerPrefs.SetString("Name","Tom"); //獲取資料: PlayerPrefs.GetInt("Index");
二、儲存資料序列化
- Serialization(序列化),可以用來將物件轉化為位元組流。
- Deserialization(反序列化),可以用來將位元組流轉換為物件。
- 常見的資料序列化方法:二進位制方法,XML方法,JSON方法
- 儲存在:記憶體、檔案、資料庫--可存於本地或雲
++下面以例項說明++:
Save類--用於儲存資訊
using System.Collections; using System.Collections.Generic; using UnityEngine; [System.Serializable] public class Save{ //怪物位置 public List<int> livingTargetPositions = new List<int>(); //怪物型別 public List<int> livingMonsterTypes = new List<int>(); //得分情況 public int shootNum = 0; public int score = 0; }
- 二進位制儲存(Binary Formatter)
- 序列化:新建或開啟一個二進位制檔案,通過二進位制格式器將物件寫入該二進位制檔案。
- 反序列化:開啟待反序列化的二進位制檔案,通過二進位制格式器將檔案解析成物件。
//二進位制方法:存檔和讀檔 private void SaveByBin() { //序列化過程(將Save物件轉換為位元組流) //建立Save物件並儲存當前遊戲狀態 Save save = CreateSaveGO(); //建立一個二進位制格式化程式 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")) { //TODO: 提示儲存成功 } } 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); //將儲存的資訊類初始遊戲 //TODO: 提示存檔不存在或為空,讀取成功 } else { //TODO: 提示存檔不存在或為空,讀取失敗 } }
- Json儲存
- JSON:是一種語言無關的傳送和接收資料的常用格式。可以使用它來跨平臺的傳輸資料。
- JSON序列化:
graph LR
物件-->JSON
- JSON反序列化:
graph LR
JSON-->物件
//JSON:存檔和讀檔
private void SaveByJson()
{
Save save = CreateSaveGO();
string filePath = Application.dataPath + "/StreamingFile" + "/byJson.json";
//利用JsonMapper將save物件轉換為Json格式的字串
string saveJsonStr = JsonMapper.ToJson(save);
//將這個字串寫入到檔案中
//建立一個StreamWriter,並將字串寫入檔案中
StreamWriter sw = new StreamWriter(filePath);
sw.Write(saveJsonStr);
//關閉StreamWriter
sw.Close();
//TODO: 提示儲存成功
}
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);//將儲存的資訊類初始遊戲
//TODO: 提示存檔不存在或為空,讀取成功
}
else
{
//TODO: 提示存檔不存在或為空,讀取失敗
}
}
儲存效果:
{
"livingTargetPositions":[0,1,2,4,5,8],
"livingMonsterTypes":[2,1,2,0,3,0],
"shootNum":18,
"score":9
}
- XML儲存
XML:擴充套件標記語言,用於標記電子檔案使其具有結構性的標記語言。
- 可以用來標記資料、定義資料型別。
- 序列化與反序列化的方式與二進位制方法十分類似。
//XML:存檔和讀檔--要根據XML檔案的結點結構進行操作
private void SaveByXml()
{
Save save = CreateSaveGO();
//建立XML檔案的儲存路徑
string filePath = Application.dataPath + "/StreamingFile" + "/byXML.txt";
//建立XML文件
XmlDocument xmlDoc = new XmlDocument();
//建立根節點,即最上層節點
XmlElement root = xmlDoc.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 = xmlDoc.CreateElement("target");
targetPosition = xmlDoc.CreateElement("targetPosition");
//設定InnerText值
targetPosition.InnerText = save.livingTargetPositions[i].ToString();
monsterType = xmlDoc.CreateElement("monsterType");
monsterType.InnerText = save.livingMonsterTypes[i].ToString();
//設定節點間的層級關係 root -- target -- (targetPosition, monsterType)
target.AppendChild(targetPosition);
target.AppendChild(monsterType);
root.AppendChild(target);
}
//設定射擊數和分數節點並設定層級關係 xmlDoc -- root --(target-- (targetPosition, monsterType), shootNum, score)
XmlElement shootNum = xmlDoc.CreateElement("shootNum");
shootNum.InnerText = save.shootNum.ToString();
root.AppendChild(shootNum);
XmlElement score = xmlDoc.CreateElement("score");
score.InnerText = save.score.ToString();
root.AppendChild(score);
xmlDoc.AppendChild(root);
xmlDoc.Save(filePath);
if(File.Exists(Application.dataPath + "/StreamingFile" + "/byXML.txt"))
{
//TODO: 提示儲存成功
}
}
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 targets = xmlDoc.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 shootNum = xmlDoc.GetElementsByTagName("shootNum");
int shootNumCount = int.Parse(shootNum[0].InnerText);
save.shootNum = shootNumCount;
XmlNodeList score = xmlDoc.GetElementsByTagName("score");
int scoreCount = int.Parse(score[0].InnerText);
save.score = scoreCount;
SetGame(save);//將儲存的資訊類初始遊戲
//TODO: 提示存檔不存在或為空,讀取成功
}
else
{
//TODO: 提示存檔不存在或為空,讀取失敗
}
}
儲存效果:
<save name="saveFile1">
<target>
<targetPosition>0</targetPosition>
<monsterType>1</monsterType>
</target>
<target>
<targetPosition>1</targetPosition>
<monsterType>3</monsterType>
</target>
<target>
<targetPosition>3</targetPosition>
<monsterType>3</monsterType>
</target>
<target>
<targetPosition>4</targetPosition>
<monsterType>0</monsterType>
</target>
<target>
<targetPosition>6</targetPosition>
<monsterType>3</monsterType>
</target>
<target>
<targetPosition>7</targetPosition>
<monsterType>0</monsterType>
</target>
<shootNum>50</shootNum>
<score>29</score>
</save>
- 三種儲存方式的對比
- 二進位制方法:簡單,但可讀性差。
- XML:可讀性強,但是檔案龐大,冗餘資訊多。
- JSON:資料格式比較簡單,易於讀寫,但是不直觀,可讀性比XML差。
- 本地儲存位置補充--關於Application.dataPath