前言
遊戲存檔的功能和重要性不需要過多敘述,實現的方法也很多樣。
對於Unity來講,最簡單的就是用PlayerPrefs來搞。但是就因爲簡單,所以能實現的功能也比較少。目前PlayerPrefs存些Int、String顯然是不夠的。
所以推薦一個C#自帶的序列化來做存檔,簡單易用,功能全面,而且簡單,會一點C#就能會。
原理
用 FileStream 和 BinaryFormatter 來將一個C#的類存成持久文件。
核心代碼很簡單,如下:
BinaryFormatter formatter = new BinaryFormatter();
FileStream saveFile = File.Create(savePath);
formatter.Serialize(saveFile, saveObject);
saveFile.Close();
實現
1、準備工作
首先要給你的存檔們準備一個文件夾來存放你的存檔,如果沒有的話就創建一個,然後需要給你打算保存的類指定一個文件名。
//Unity的話推薦 Application.persistentDataPath
//這裏寫的是一個獲取文件路徑+創建存檔文件夾二合一功能的方法;
/// <summary>
/// 獲取遊戲存檔的文件夾路徑;
/// </summary>
static string GetGameSaveFilePath(string name)
{
string PersistantPath=Application.persistentDataPath;
string Dir = PersistantPath + "/Save";
if (!Directory.Exists(Dir))
{
Directory.CreateDirectory(Dir);
}
return Dir + "/" + name + ".Save";
}
這裏返回具體文件的時候,我給加了個後綴名 .Save,其實這個是隨便加得。願意加什麼後綴就加什麼後綴,自定義的,可以當成自己的存檔標記(最好不要與現有的應用程序衝突)。
這樣就把存檔定在一個文件夾下面了,叫做XXX.Save的文件。這就是我們預計存的文件名。
2、文件保存
先上代碼:
public static void Save(string fileName, object saveObject)
{
//獲取文件路徑,有兩個地方可以選擇
string savePath = GetGameSaveFilePath(fileName);
Logger.Log("保存文件:" + savePath);
BinaryFormatter formatter = new BinaryFormatter();
FileStream saveFile = File.Create(savePath);
formatter.Serialize(saveFile, saveObject);
saveFile.Close();
}
這裏的saveObject是隨便你自己寫的什麼類都可以,沒有什麼特定的要求。
一般沒有什麼報錯就算是存下來了~~
3、文件讀取
一般來講讀取的時候是一股腦都讀取的,最後選擇其中一個來進行遊戲。
下面這個方法是獲取之前路徑下的所有文件,以FileInfo的形式返回。
/// <summary>
/// 獲取存檔路徑下的所有.Save文件;
/// </summary>
/// <returns></returns>
static FileInfo[] GetAllSaveFiles()
{
string Dir = Application.persistentDataPath + "/Save";
if (!Directory.Exists(Dir))
{
return null;
}
DirectoryInfo direct = new DirectoryInfo(Dir);
return direct.GetFiles("*.Save", SearchOption.AllDirectories);
}
這下面這個方法是加載一個具體的文件:
public static object Load(string fileName)
{
string savePath = GetGameSaveFilePath(fileName);
Logger.Log("讀取文件:" + savePath);
BinaryFormatter formatter = new BinaryFormatter();
if (File.Exists(savePath))
{
FileStream saveFile = File.Open(savePath, FileMode.Open, FileAccess.Read, FileShare.Read);
object returnObject = formatter.Deserialize(saveFile);
saveFile.Close();
return returnObject;
}
else
{
Logger.LogWarning("文件不存在: " + savePath);
return null;
}
}
這樣加載完只有就有是一個Object了,可以用 Object as 的方法轉成自己定義的類。
4、存檔的刪除
用C#的刪除就可以,指定一個文件路徑,直接刪就完事了。
/// <summary>
/// 刪除;
/// </summary>
/// <param name="fileName"></param>
public static void Delete(string fileName)
{
string curPath = GetGameSaveFilePath(fileName);
Logger.Log("刪除文件:" + curPath);
if (File.Exists(curPath))
{
File.Delete(curPath);
}
}
備註
1、存儲的限制
用來存儲的類中所有的屬性都得是可存儲的(似乎是廢話),否則會報錯。理論上你在類裏引用別的類,就需要在被引用的類中加上 [System.Serializable] 標記。如果類中有些什麼東西不能存反正會報錯,大家看着報錯自己改改就好了。
2、如何不保存
如果類中的某些屬性/字段不需要保存,就在這個字段上加上 [System.NonSerialized] 。
所以如果使用了一些字段又不需要保存的話,可以加上這個Tag,然後就可以減少一下文件大小。
推薦一個SaveMangaer的寫法的博客: