存檔
參考
使用沒有存檔的軟體,就像吃飯不給容器一般。
故存檔必然是極為重要的。
下面介紹Unity的幾種存檔方式。
程式碼出處
Part.1——PlayerPrefs
應該是最簡單的存檔方式。
但侷限性也是顯然的,只能儲存int, float, string
三種型別,就像在檔案中儲存了三個map <string, int / float / string>
。
PlayerPrefs.SetInt("田所浩二", 114514); // 存
PlayerPrefs.SetString("濤哥", "原神");
string players_id = PlayerPrefs.GetString("濤哥"); // 讀
Part.2——儲存資料序列化
分為三種:二進位制方法、XML方法、JSON方法,各有千秋。
大體就是
序列化 物件 -> 位元組流
反序列化 位元組流 -> 物件
先建立一個Save類,用於記錄需要儲存的東西
public class Save
{
public List <string> HZOI_name = new List <string>();
public int id;
}
1. 二進位制方式
使用二進位制檔案進行序列化與反序列化
private void Save_By_Bin()
{
Save save = Create_Save();
BinaryFormatter bf = new BinaryFormatter(); // 建立二進位制格式化程序
FileStream fileStream = File.Create(Application.dataPath + "/StreamingFile" + "/byBin.txt"); // 建立檔案流
bf.Serialize(fileStream, save);
fileStream.Close(); // 關閉
if (File.Exists(Application.dataPath + "/StreamingFile" + "/byBin.txt"))
{
Debug.Log("儲存成功");
}
}
private void Load_By_Bin()
{
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)bf.Deserialize(fileStream);
fileStream.Close();
Set_Game(save);
Debug.Log("成功");
}
else
{
Debug.Log("What are you doing?");
}
}
2. JSON方法
使用JSON進行序列化與反序列化
//JSON:存檔和讀檔
private void SaveByJson()
{
Save save = Create_Save();
string filePath = Application.dataPath + "/StreamingFile" + "/byJson.json";
//利用JsonMapper將save物件轉換為Json格式的字串
string saveJsonStr = JsonMapper.ToJson(save);
//將這個字串寫入到檔案中
//建立一個StreamWriter,並將字串寫入檔案中
StreamWriter sw = new StreamWriter(filePath);
sw.Write(saveJsonStr);
sw.Close();
if (File.Exists(Application.dataPath + "/StreamingFile" + "/byBin.txt"))
{
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("What are you doing?");
}
}
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), id, score)
XmlElement id = xmlDoc.CreateElement("id");
id.InnerText = save.id.ToString();
root.AppendChild(id);
xmlDoc.AppendChild(root);
xmlDoc.Save(filePath);
if (File.Exists(Application.dataPath + "/StreamingFile" + "/byBin.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 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 id = xmlDoc.GetElementsByTagName("id");
int shootNumCount = int.Parse(id[0].InnerText);
save.id = shootNumCount;
SetGame(save);//將儲存的資訊類初始遊戲
//TODO: 提示存檔不存在或為空,讀取成功
Debug.Log("成功");
}
else
{
Debug.Log("What are you doing?");
}
}
Part.3 總結
二進位制方法:簡單簡潔,但可讀性極差
JSON方法:可讀性好,感覺比較符合人類直覺
XML:冗長,可讀性好(?沒感覺可讀性太好,可能是我太蒻了嗚嗚嗚)