前言
游戏存档的功能和重要性不需要过多叙述,实现的方法也很多样。
对于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的写法的博客: