通过实例学习:游戏的存档与读档(Unity 2017.2)DAY3(完结)

1.设置Target位置和怪物类型

修改TargetManager中的一些代码

    //保存所有该目标下的怪物和当前激活状态下的怪物
    public GameObject[] monsters;
    public GameObject activeMaonster = null;
    //表示目标所在的位置(0-8)
    public int targetPosition;

    //通过Type来激活怪物
    public void ActivateMonsterByType(int type)
    {
        StopAllCoroutines();
        if (activeMaonster != null)
        {
            activeMaonster.GetComponent<BoxCollider>().enabled = false;
            activeMaonster.SetActive(false);
            activeMaonster = null;
        }
        activeMaonster = monsters[type];
        activeMaonster.SetActive(true);
        activeMaonster.GetComponent<BoxCollider>().enabled = true;
        StartCoroutine("DeathTimer");
    }

2.复制Target并完善

3.创建Save保存类

首先创建一个Save类

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[System.Serializable]
public class Save  {

    public List<int> livingTargetPositions = new List<int>();
    public List<int> livingMonsterTypes = new List<int>();

    public int shootNum = 0;
    public int score = 0; 
}

在GameManager中添加创建Save的方法

    private Save CreateSaveGo()
    {
        //新建Save对象
        Save save = new Save();
        //遍历所有的Target
        //如果其中有处于激活状态的怪物,就把该target的位置信息和激活状态的怪物的类型添加到List中
        foreach(GameObject targetGo in targetGos)
        {
            TargetManager targetManager = targetGo.GetComponent<TargetManager>();
            if (targetManager.activeMaonster != null)
            {
                save.livingTargetPositions.Add(targetManager.targetPosition);
                int type = targetManager.activeMaonster.GetComponent<MonsterManager>().monsterType;
                save.livingMonsterTypes.Add(type);              
            }
        }
        //把shootNum和score保存在Save对象中
        save.shootNum = UIManager._instance.shootNum;
        save.score = UIManager._instance.score;
        //返回该Save对象
        return save;
    }

4.保存游戏(二进制方法)

    //二进制:读档和存档
    private void SaveByBin()
    {
        //序列化过程(将Save对象转换为字节流)
        //创建Save对象并保存当前游戏状态
        Save save = CreateSaveGo();
        //创建一个二进制格式化程序
        BinaryFormatter bf = new BinaryFormatter();
        //创建一个文件流
        FileStream fileStream = File.Create(Application.dataPath + "/StreamingFile" + "/byBin.txt");
        //用二进制格式化程序的序列化方法来序列化Save对象,参数:创建的文件流和需要序列化的对象
        bf.Serialize(fileStream, save);
        //关闭流
        fileStream.Close();
    }

5.读取游戏(二进制方法)

在GameManager中添加读取游戏的方法

    private void LoadByBin()
    {
        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 = (Save)bf.Deserialize(fileStream);
            //关闭文件流
            fileStream.Close();
            SetGame(save);
        }
        else
        {
            UIManager._instance.ShowMessage("存档文件不存在!");
        }
    }
    private void SetGame(Save save)
    {
        //先将所有的target里面的怪物清空,并重置所有的计时
        foreach(GameObject targetGo in targetGos)
        {
            targetGo.GetComponent<TargetManager>().UpdateMonsters();
        }
        //通过反序列化得到Save对象中存储的信息,激活指定的怪物
        for(int i = 0; i < save.livingTargetPositions.Count; i++)
        {
            int position = save.livingTargetPositions[i];
            int type = save.livingMonsterTypes[i];
            targetGos[position].GetComponent<TargetManager>().ActivateMonsterByType(type);
        }
        //更新UI显示
        UIManager._instance.shootNum = save.shootNum;
        UIManager._instance.score = save.score;
        //调整为为暂停状态
        UnPause();
    }

    //加载游戏
    public void LoadGame()
    {
        LoadByBin();
        UIManager._instance.ShowMessage("");
    }

结果如下

6.保存游戏(JSON)

在GameManager中添加用Json保存游戏的方法

    using LitJson;
    private void SaveByJson()
    {
        Save save = CreateSaveGo();
        string filePath = Application.dataPath + "/StreamingFile" + "/byJson.json";
        //利用JsonMapper将save对象转换为Json格式的字符串
        string saveJsonStr = JsonMapper.ToJson(save);
        //将这个字符串写入到文件中
        //创建一个StreamWriter,并将字符串写入文件中
        StreamWriter sw = new StreamWriter(filePath);
        sw.Write(saveJsonStr);
        //关闭StreamWriter
        sw.Close();

        UIManager._instance.ShowMessage("保存成功!");
    }

结果如下

{"livingTargetPositions":[1,3,4,5,8],"livingMonsterTypes":[2,0,0,2,3],"shootNum":4,"score":2}

7.读取游戏(JSON)

    private void LoadByJson()
    {
        string filePath = Application.dataPath + "/StreamingFile" + "/byJson.json";
        if(File.Exists(Application.dataPath + "/StreamingFile" + "/byJson.json"))
        {
            //创建一个StreamReader,用来读取流
            StreamReader sr = new StreamReader(filePath);
            //将读取到的流赋值给jsonStr
            string jsonStr = sr.ReadToEnd();
            sr.Close();

            //将字符串jsonStr转换为Save对象
            Save save = JsonMapper.ToObject<Save>(jsonStr);
            SetGame(save);
            UIManager._instance.ShowMessage("");
        }
        else
        {
            UIManager._instance.ShowMessage("存档文件不存在!");
        }
    }

8.保存游戏(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 --(targettarget -- (targetPosition,monsterType),shootNum,score)
        XmlElement shootNum = xmlDoc.CreateElement("shootNum");
        shootNum.InnerText = save.shootNum.ToString();
        root.AppendChild(shootNum);

        XmlElement score = xmlDoc.CreateElement("score");
        score.InnerText = save.score.ToString();
        root.AppendChild(score);

        xmlDoc.AppendChild(root);
        xmlDoc.Save(filePath);

        if(File.Exists(Application.dataPath + "/StreamingFile" + "/byXML.txt"))
        {
            UIManager._instance.ShowMessage("保存成功");
        }
    }

结果如下

<save name="saveFile1">
  <target>
    <targetPosition>0</targetPosition>
    <monsterType>2</monsterType>
  </target>
  <target>
    <targetPosition>1</targetPosition>
    <monsterType>1</monsterType>
  </target>
  <target>
    <targetPosition>2</targetPosition>
    <monsterType>1</monsterType>
  </target>
  <target>
    <targetPosition>3</targetPosition>
    <monsterType>1</monsterType>
  </target>
  <target>
    <targetPosition>4</targetPosition>
    <monsterType>3</monsterType>
  </target>
  <target>
    <targetPosition>5</targetPosition>
    <monsterType>2</monsterType>
  </target>
  <target>
    <targetPosition>8</targetPosition>
    <monsterType>0</monsterType>
  </target>
  <shootNum>2</shootNum>
  <score>1</score>
</save>

9.读取游戏(XML)

    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 shootNum = xmlDoc.GetElementsByTagName("shootNum");
            int shootNumCount = int.Parse(shootNum[0].InnerText);
            save.shootNum = shootNumCount;

            XmlNodeList score = xmlDoc.GetElementsByTagName("score");
            int scoreCount = int.Parse(score[0].InnerText);
            save.score = scoreCount;

            SetGame(save);
            UIManager._instance.ShowMessage("");
        }
        else
        {
            UIManager._instance.ShowMessage("存档文件不存在!");
        }
    }

猜你喜欢

转载自blog.csdn.net/kouzhuanjing1849/article/details/83929603