前面使用的PlayerPrefs虽然简单操作,但是对于大量数据的存储显得难以处理,因为PlayerPrefs通过键值对来存储某个信息,这就意味着面临大量数据时,这不是个好的方法。
现在我想做的时去存储整个游戏世界的敌人位置,状态信息,敌人有很多个(我暂且创建3个),基本思路如下:
1.创建一个可序列化的类Save,让它作为一个单独的类,不继承任何类。在类前加上[System.Serializable]即可。
2.明确需要存储的信息,比如敌人的位置,可以写两个列表positionX,positionY分别表示各个敌人的位置信息。
3.创建函数SaveBySerialization和LoadByDeSerialization分别对应UI上的save和load按钮,再创建一个类型为Save的函数createSaveGameObject,在save时将当前敌人信息写入Save类。
4.通过SaveBySerialization来进行文件操作,将Save类转变为二进制文件。
5.在玩家按下load时,通过LoadByDeSerialization来反编译为Save类,再遍历读取Save类里的数据,将其赋值给敌人。
首先,我想要存储敌人的位置信息,且当我消灭了敌人时(save之后),load依然能使它出现在预期位置,并且状态正确。
在Save中写三个列表:
[System.Serializable]
public class Save
{
//save enemies position and hp information
public List positionX=new List();
public List positionY=new List();
public List broken=new List();
}
接下来我要在createSaveGameObject中把当前敌人的信息传给Save类了,但是我不能凭空知道这些信息,需要我的代码与Unity关联起来才行,所以我要先在GameManage中加入这样一句:
public List
public class GameManage : MonoBehaviour
{
public static GameManage instance;
public bool IsPaused;
public List enemies=new List();
private void Awake() {
if(instance==null)
{
instance=this;
}else{
if(instance!=this)
{
Destroy(gameObject);
}
}
DontDestroyOnLoad(gameObject);
}
}
这样我就能把游戏世界里的敌人全部放入这个列表里了,由于GanmeManage被我设置为了单例,所以我可以全局调用。
现在我就可以给Save类赋值了:
private Save createSaveGameObject()
{
Save save=new Save();
foreach(EnemyController enemy in GameManage.instance.enemies)
{
save.broken.Add(enemy.broken);
save.positionX.Add(enemy.PositionX);
save.positionY.Add(enemy.PositionY);
}
return save;
}
现在Save类已经存储了敌人的位置信息,以及是否损坏,接下来我要把这个类转化为二进制文件,这里的关键在于Serialize函数,它属于类BinaryFormatter,引入这个类需要using System.Runtime.Serialization.Formatters.Binary; 它有两个参数(a,b)a为文件流,b为类,作用是把类以文件流的形式写入文件流所在的文件。文件流FileStream需要using System.IO;
private void SaveBySerialization()
{
Save save=createSaveGameObject();
BinaryFormatter bf=new BinaryFormatter();
FileStream fileStream=File.Create(@"F:\unity games\learning\My project\Assets\scripts\LoadGame\Data.text");
bf.Serialize(fileStream,save); //将save以二进制存入fileStream
fileStream.Close();
}
现在就创建好了一个Data.text的二进制文件来存放Save类的数据,读取也是类似的操作,由于我的这个游戏击败了敌人敌人不会消失而是变换状态,所以在save前判定broke为false时(被击败),不做操作,在save后判定broke为false时,说明save前为true,这样就执行销毁(save后的broken为false状态),重新生成一个(broken为true的状态)。
private void LoadByDeSerialization()
{
if(File.Exists(@"F:\unity games\learning\My project\Assets\scripts\LoadGame\Data.text"))
{
BinaryFormatter bf=new BinaryFormatter();
FileStream fileStream=File.Open(@"F:\unity games\learning\My project\Assets\scripts\LoadGame\Data.text",FileMode.Open);
Save save=bf.Deserialize(fileStream) as Save;
fileStream.Close();
for(int i=0;i
在游戏中已经可以正常加载了,但是经测试还有一个问题是:当退出游戏后再次加载会出现异常,原因是忘了保存broken,之后还要改变状态,这样写感觉不太好,或许会有更好的方法吧。
private void LoadByDeSerialization()
{
if(File.Exists(@"F:\unity games\learning\My project\Assets\scripts\LoadGame\Data.text"))
{
BinaryFormatter bf=new BinaryFormatter();
FileStream fileStream=File.Open(@"F:\unity games\learning\My project\Assets\scripts\LoadGame\Data.text",FileMode.Open);
Save save=bf.Deserialize(fileStream) as Save;
fileStream.Close();
for(int i=0;i