游戏开发日志14(利用二进制来存储数据)

前面使用的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 enemies=new 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

你可能感兴趣的:(unity数据储存,游戏开发日志,unity,游戏引擎)