zoukankan      html  css  js  c++  java
  • 06、游戏的存档和读档

    1、保存的数据类:

     1 using System.Collections;
     2 using System.Collections.Generic;
     3 using UnityEngine;
     4 
     5 [System.Serializable]
     6 public class Save
     7 {
     8     public List<int> livingTargetPosition = new List<int>();       //用来保存有怪物的位置信息
     9     public List<int> livingMonsterType = new List<int>();          //保存生成的怪物类型
    10 
    11     public int shootNumebr=0;           //射击数
    12     public int score = 0;        //分数
    13 }

    2、游戏管理器,用来管理游戏的保存和加载

      1 using System.Collections;
      2 using System.Collections.Generic;
      3 using UnityEngine;
      4 using UnityEngine.UI;
      5 using System.IO;
      6 using System.Runtime.Serialization.Formatters.Binary;           //二进制转换器
      7 using LitJson;              //json的命名空间引入
      8 using System.Xml;           //引入xml的命名空间
      9     
     10 public class GameManager : MonoBehaviour
     11 {
     12     private static GameManager _instance;
     13     public static GameManager Instace
     14     {
     15         get
     16         {
     17             return _instance;
     18         }
     19         set
     20         {
     21             _instance = value;
     22         }
     23     }
     24     private void Awake()
     25     {
     26         _instance = this;
     27 
     28     }
     29 
     30     public GameObject MenuGameObject;              //菜单游戏物体
     31     public GameObject[] targets;                   //每个格子都会有怪物生成,则要一一获取
     32     public bool IsPause = true;                     //默认菜单面板显示出来就是暂停状态
     33 
     34     private void Start()
     35     {
     36         IsPause = true;
     37         Pause();                                    //默认菜单面板显示出来就是暂停状态
     38     }
     39 
     40     private void Update()
     41     {
     42         if (Input.GetKeyDown(KeyCode.Escape))
     43         {
     44             Pause();                         //当按下了ESC键就调出菜单面板
     45         }
     46     }
     47 
     48     /// <summary>
     49     /// 通过生成的游戏数据,然后创建保存类,将相关的数据写到Sava类中进行保存
     50     /// //只要调用这个方法,就会得到一个保存好数据的Save类
     51     /// </summary>
     52     /// <returns></returns>
     53     private Save CreateSave()
     54     {
     55         Save save = new Save();     //先创建这个对象
     56         foreach (GameObject targetGo in targets)
     57         {
     58             TargetManager targetManager = targetGo.GetComponent<TargetManager>();
     59             if(targetManager.activateMoster!=null)
     60             {
     61                 //如果有不为空的,也就是在游戏场景中生成了的,
     62                 save.livingTargetPosition.Add(targetManager.targetPosition);            //则要进行保存
     63                 save.livingMonsterType.Add(targetManager.activateMoster.GetComponent<MosterManager>().mosterType);  //保存怪物类型
     64             }
     65         }
     66         save.shootNumebr = UIManager.Instance.shootNumber;
     67         save.score = UIManager.Instance.scoreNumber;                //将分数和射击数进行保存
     68 
     69         return save;        
     70     }
     71     /// <summary>
     72     /// 通过读档,将得到的数据运用到游戏中,分数、射击数、怪物位置、怪物类型
     73     /// </summary>
     74     /// <param name="save">读取到的文件类</param>
     75     private void SetGame(Save save)
     76     {
     77         foreach (GameObject targetGo in targets)
     78         {
     79             targetGo.GetComponent<TargetManager>().UpdateMoster();      //通过数据读取来设计游戏中的场景时,要先将场景中有的进行清空
     80         }
     81 
     82         for (int i = 0; i < save.livingTargetPosition.Count; i++)
     83         {
     84             int position = save.livingTargetPosition[i];            //得到在哪个格子里面进行生成
     85             int type = save.livingMonsterType[i];                   //得到生成那种类型的
     86             targets[position].GetComponent<TargetManager>().ActivateMonsterByType(type);        //通过怪物下标来进行生成
     87         }
     88 
     89         UIManager.Instance.shootNumber = save.shootNumebr;
     90         UIManager.Instance.scoreNumber = save.score;                //更新得分和成绩
     91     }
     92 
     93 
     94 
     95 
     96     //二进制:存档和读档
     97     private void SaveByBin()
     98     {
     99         //1、首先得到要保存的Save类
    100         Save save = CreateSave();          
    101         //2、创建一个二进制转化程序
    102         BinaryFormatter binF = new BinaryFormatter();
    103         //3、得到要保存数据的数据流
    104         FileStream fileStream = File.Create(Application.dataPath + "/StreamingFile" + "/Bin.txt");
    105         //4、进行序列化,写入
    106         binF.Serialize(fileStream, save);
    107         //5、关闭
    108         fileStream.Close();
    109 
    110         if(File.Exists((Application.dataPath + "/StreamingFile" + "/Bin.txt")))
    111         {
    112             //如果保存成功了,显示保存成功的提示
    113             UIManager.Instance.Message("保存成功");
    114         }
    115     }
    116 
    117     private void LoadByBin()
    118     {
    119         //1、先判断存档文件是否存在
    120         if(File.Exists(Application.dataPath + "/StreamingFile" + "/Bin.txt"))
    121         { 
    122             //2、创建二进制转换器
    123             BinaryFormatter binf = new BinaryFormatter();
    124             //3、得到文件流
    125             FileStream fileStrem = File.Open(Application.dataPath + "/StreamingFile" + "/Bin.txt", FileMode.Open);
    126             //4、通过二进制逆转换器得到数据
    127             Save save = (Save)binf.Deserialize(fileStrem);      //得到数据
    128             //5、关闭
    129             fileStrem.Close();
    130             //6、将数据进行保存
    131             SetGame(save);
    132 
    133             UIManager.Instance.Message("读档成功");
    134         }
    135         else
    136         {
    137             UIManager.Instance.Message("文档不存在");
    138         }
    139     }
    140 
    141 
    142     //XML:存档和读档
    143     private void SaveByXml()
    144     {
    145         //1、创建save对象
    146         Save save = CreateSave();
    147         //2、创建XML文件的存储路径
    148         string filePath = Application.dataPath + "/StreamingFile" + "/byXml.xml";
    149         //3、创建XML文档
    150         XmlDocument xmlDoc = new XmlDocument();
    151         //4、创建根节点,名字为Save,注意,一个XML文档只有一个根节点,就和html语言一样
    152         XmlElement root = xmlDoc.CreateElement("Save");
    153         //5、设置根节点的属性,也可以不设置
    154         root.SetAttribute("namne","saveFile");
    155 
    156         //6、创建XmlElement
    157         XmlElement target;
    158         XmlElement targetPosition;
    159         XmlElement targetType;
    160 
    161         for (int i = 0; i < save.livingTargetPosition.Count; i++)
    162         {
    163             target = xmlDoc.CreateElement("Target");
    164 
    165             //创建其中一个属性 设置innertext的值
    166             targetPosition = xmlDoc.CreateElement("targetPosition");
    167             targetPosition.InnerText = save.livingTargetPosition[i].ToString();
    168 
    169             targetType = xmlDoc.CreateElement("targetType");
    170             targetType.InnerText = save.livingMonsterType[i].ToString();
    171 
    172             //设置层级关系
    173             target.AppendChild(targetPosition);
    174             target.AppendChild(targetType);
    175             root.AppendChild(target);
    176         }
    177         XmlElement UI;
    178         XmlElement shootNumber;
    179         XmlElement score;
    180 
    181         UI = xmlDoc.CreateElement("UI");
    182         shootNumber = xmlDoc.CreateElement("ShootNumber");
    183         score = xmlDoc.CreateElement("Score");
    184 
    185         //存入数据
    186         shootNumber.InnerText = save.shootNumebr.ToString();
    187         score.InnerText = save.score.ToString();
    188 
    189         //设置层级关系
    190         UI.AppendChild(shootNumber);
    191         UI.AppendChild(score);
    192         root.AppendChild(UI);
    193 
    194         //将根节点添加到xml文档中
    195         xmlDoc.AppendChild(root);
    196         //保存xml文档
    197         xmlDoc.Save(filePath);
    198 
    199         if(File.Exists(filePath))
    200         {
    201             UIManager.Instance.Message("保存成功");
    202         }
    203 
    204     }
    205     private void LoadByXml()
    206     {
    207         string filePath= Application.dataPath + "/StreamingFile" + "/byXml.xml";
    208         //如果存在文件的话
    209         if(File.Exists(filePath))
    210         {
    211             Save save = new Save();
    212             //加载XML文档
    213             XmlDocument xmlDoc = new XmlDocument();
    214             xmlDoc.Load(filePath);
    215             //通过节点名称来获取元素,注意,文档中会有多个该节点,结果为XmlNodeList类型
    216             XmlNodeList targets =xmlDoc.GetElementsByTagName("Target");
    217             if(targets.Count!=0)
    218             {
    219                 for (int i = 0; i < targets.Count; i++)
    220                 {
    221                     //每一个target节点下面还有子节点,数据存在了对应的子节点下面
    222                     XmlNode targetPosition = targets[i].ChildNodes[0];
    223                     int targetPositionValue = int.Parse(targetPosition.InnerText);
    224                     save.livingTargetPosition.Add(targetPositionValue);
    225 
    226                     XmlNode targetType = targets[i].ChildNodes[1];
    227                     int targetTypeValue = int.Parse(targetType.InnerText);
    228                     save.livingMonsterType.Add(targetTypeValue);
    229 
    230                 }
    231             }
    232 
    233             XmlNodeList UI = xmlDoc.GetElementsByTagName("UI");
    234             if(UI.Count!=0)
    235             {
    236                 foreach (XmlNode ui in UI)
    237                 {
    238                     XmlNode shootNumber = ui.ChildNodes[0];
    239                     int shootNumberValue = int.Parse(shootNumber.InnerText);
    240                     save.shootNumebr = shootNumberValue;
    241 
    242                     XmlNode score = ui.ChildNodes[1];
    243                     int scoreValue = int.Parse(score.InnerText);
    244                     save.score = scoreValue;
    245                 }
    246             }
    247 
    248             //将得到的数据进行应用
    249             SetGame(save);      
    250 
    251             UIManager.Instance.Message("文档加载成功");
    252         }
    253         else
    254         {
    255             UIManager.Instance.Message("文档不存在");
    256         }
    257 
    258         
    259 
    260     }
    261 
    262 
    263     //JSON:存档和读档
    264     private void SaveByJson()
    265     {
    266         //1、创建save对象
    267         Save save = CreateSave();
    268         //2、得到要放置json文件的地址
    269         string filePath = Application.dataPath + "/StreamingFile" + "/byJson.json";
    270         //3、将save对象转换为json字符串
    271         string saveJsonString = JsonMapper.ToJson(save);
    272         //4、 //设置为写入的文件流
    273         StreamWriter writer = new StreamWriter(filePath);
    274         //5、写入
    275         writer.Write(saveJsonString);
    276         //6、关闭
    277         writer.Close();
    278         if(File.Exists(Application.dataPath + "/StreamingFile" + "/byJson.json"))
    279         {
    280             UIManager.Instance.Message("保存成功");
    281         }
    282 
    283 
    284     }
    285     private void LoadByJson()
    286     {
    287         string filrPath = Application.dataPath + "/StreamingFile" + "/byJson.json";
    288         if(File.Exists(filrPath))
    289         {
    290             //1、如果文件存在
    291             StreamReader reader = new StreamReader(filrPath);
    292             //2、通过读取数据流读到json文件中的信息,转化为字符串
    293             string loadJsonString = reader.ReadToEnd();         //读取到结尾
    294             //3、将json文件转化为save对象
    295             Save save = JsonMapper.ToObject<Save>(loadJsonString);
    296             //4、将数据应用到游戏中
    297             SetGame(save);
    298             UIManager.Instance.Message("读取成功");
    299         }
    300         else
    301         {
    302             UIManager.Instance.Message("文档不存在");
    303         }
    304 
    305     }
    306 
    307     /// <summary>
    308     /// 暂停游戏
    309     /// </summary>
    310     private void Pause()
    311     {
    312         MenuGameObject.SetActive(true);
    313         IsPause = true;
    314         Time.timeScale = 0;         //暂停游戏
    315         Cursor.visible = true;
    316     }
    317 
    318 
    319     /// <summary>
    320     /// 非暂停状态
    321     /// </summary>
    322     private void UpPause()
    323     {
    324         IsPause = false;
    325         MenuGameObject.SetActive(false);
    326         Time.timeScale = 1;         //继续进行游戏
    327         Cursor.visible = false;
    328     }
    329 
    330     /// <summary>
    331     /// 继续游戏
    332     /// </summary>
    333     public void OnContinueGameButtonClick()
    334     {
    335         UpPause();
    336     }
    337 
    338     /// <summary>
    339     /// 退出游戏
    340     /// </summary>
    341     public void OnQuietButtonClick()
    342     {
    343     #if UNITY_EDITOR
    344          UnityEditor.EditorApplication.isPlaying = false;
    345     # else
    346          Application.Quit();    
    347     #endif
    348     }
    349 
    350     /// <summary>
    351     ///新游戏
    352     /// </summary>
    353     public void OnNewGameButtonClick()
    354     {
    355         foreach (GameObject target in targets)
    356         {
    357             target.GetComponent<TargetManager>().UpdateMoster();            //对场景中的每一个敌人进行消息传递,进行更新
    358         }
    359         UIManager.Instance.shootNumber = 0;
    360         UIManager.Instance.scoreNumber = 0;         //将分数进行清零
    361         UpPause();
    362     }
    363 
    364     /// <summary>
    365     /// 保存数据
    366     /// </summary>
    367     public void OnSaveButtonClick()
    368     {
    369         UIManager.Instance.Message("");
    370         //SaveByBin();            //二进制保存
    371         //SaveByJson();
    372         SaveByXml();
    373         StartCoroutine(HideMessage());
    374     }
    375 
    376     /// <summary>
    377     /// 加载数据
    378     /// </summary>
    379     public void OnLoadButtonClick()
    380     {
    381         UIManager.Instance.Message("");
    382         //LoadByBin();
    383         //LoadByJson();
    384         LoadByXml();
    385         StartCoroutine(HideMessage());
    386     }
    387 
    388     /// <summary>
    389     /// 在一定时间内将帮助文档进行隐藏
    390     /// </summary>
    391     /// <returns></returns>
    392    IEnumerator HideMessage()
    393     {
    394         yield return new WaitForSeconds(1.0f);
    395         UIManager.Instance.message_Text.gameObject.SetActive(false);
    396     }
    397 }

    3、显示TargetManager和UIManager两个类方便阅读

      1 using System.Collections;
      2 using System.Collections.Generic;
      3 using UnityEngine;
      4 using UnityEngine.UI;
      5 
      6 public class UIManager : MonoBehaviour
      7 {
      8 
      9     private static UIManager _instace;
     10     public static UIManager Instance
     11     {
     12         set
     13         {
     14             _instace = value;
     15         }
     16         get
     17         {
     18             return _instace;
     19         }
     20     }
     21     private void Awake()
     22     {
     23         _instace = this;
     24     } 
     25 
     26     public Text shootNumber_Text;
     27     public Text scoreNumber_Text;
     28     public Toggle musicToggle;
     29     public Text message_Text;           //用来显示保存、加载成功的
     30 
     31     public int shootNumber = 0;
     32     public int scoreNumber = 0;
     33 
     34     public AudioSource music;
     35 
     36 
     37     private void Start()
     38     {
     39         message_Text.gameObject.SetActive(false);
     40     }
     41 
     42     private void Update()
     43     {
     44         UpdateUI();     //更新UI显示   
     45 
     46 
     47 
     48         //如果存在声音控制的键值
     49         if(PlayerPrefs.HasKey("MusicOn"))
     50         {
     51             if(PlayerPrefs.GetInt("MusicOn")==0)
     52             {
     53                 musicToggle.isOn = false;
     54                 music.enabled = false;
     55             }
     56             else if(PlayerPrefs.GetInt("MusicOn")==1)
     57             {
     58                 musicToggle.isOn = true;
     59                 music.enabled = true;
     60             }
     61         }
     62         //如果不存在这个键的话,就默认设置为播放状态
     63         else
     64         {
     65             musicToggle.isOn = true;
     66             music.enabled = true;
     67         }
     68 
     69 
     70     }
     71 
     72 
     73     /// <summary>
     74     /// 声音开光控制
     75     /// 使用了PlayerPrefs的保存方法来进行保存
     76     /// </summary>
     77     public void MusicSwitch()
     78     {
     79         if(musicToggle.isOn==true)
     80         {   
     81             music.enabled = true;
     82             PlayerPrefs.SetInt("MusicOn", 1);           //为1表示播放音乐,为0表示暂停音乐
     83         }
     84         else
     85         {        
     86             music.enabled = false;
     87             PlayerPrefs.SetInt("MusicOn", 0);
     88         }
     89 
     90         PlayerPrefs.Save();         //注意,在设置完值后,一定要进行保存,否则结果是无法进行保存的
     91     }
     92 
     93 
     94 
     95 
     96 
     97     /// <summary>
     98     /// 更新Ui显示的方法
     99     /// </summary>
    100     private void UpdateUI()
    101     {
    102         shootNumber_Text.text = shootNumber.ToString();
    103         scoreNumber_Text.text = scoreNumber.ToString();
    104     }
    105     /// <summary>
    106     /// 增加射击数的
    107     /// </summary>
    108     public void AddShootNumber()
    109     {
    110         shootNumber += 1;
    111     }
    112 
    113     /// <summary>
    114     /// 增加分数的
    115     /// </summary>
    116     public void AddScoreNumber()
    117     {
    118         scoreNumber += 1;
    119     }
    120 
    121     /// <summary>
    122     /// 显示加载、保存成功的提示消息的
    123     /// </summary>
    124     /// <param name="message">保存成功、保存失败</param>
    125     public void Message(string message)
    126     {
    127         message_Text.text = message;
    128         message_Text.gameObject.SetActive(true);
    129     }
    130 }
      1 using System.Collections;
      2 using System.Collections.Generic;
      3 using UnityEngine;
      4 
      5 public class TargetManager : MonoBehaviour
      6 {
      7     //这里不能用单例模式,因为在游戏中会生成多个相同的对象,
      8     //到后面就不能正确的知道是那个TargetManager了
      9     //private static TargetManager _instance;
     10     //public static TargetManager Instance
     11     //{
     12     //    get
     13     //    {
     14     //        return _instance;
     15     //    }
     16     //    set
     17     //    {
     18     //        _instance = value;
     19     //    }
     20     //}
     21     //private void Awake()
     22     //{
     23     //    _instance = this;
     24     //}
     25 
     26     public GameObject[] mosters;
     27     public GameObject activateMoster=null;         //这个是用来取得当前实例出来的怪物
     28     public int targetPosition;          //用来设置怪物的生成位置,要被保存的
     29 
     30     private void Start()
     31     {
     32         //一开始先做预判的处理
     33         foreach (GameObject moster in mosters)
     34         {
     35             moster.GetComponent<BoxCollider>().enabled = false;
     36             moster.SetActive (false);
     37         }
     38         StartCoroutine(AliveTiemr());
     39     }
     40 
     41 
     42 
     43     /// <summary>
     44     /// 等待多久进行怪物的生成的协程
     45     /// </summary>
     46     /// <returns></returns>
     47     IEnumerator AliveTiemr()
     48     {
     49         yield return new WaitForSeconds(Random.Range(1, 5));            //等待个随机1-4秒再生成
     50         ActivateMoster();
     51         StartCoroutine(DeathTimer());
     52     }
     53 
     54     /// <summary>
     55     /// 控制怪物在生成一段时间后自动进行消失
     56     /// </summary>
     57     /// <returns></returns>
     58     IEnumerator DeathTimer()
     59     {
     60         yield return new WaitForSeconds(Random .Range(3f,8.0f));
     61         DeActivateMoster();
     62     }
     63 
     64 
     65 
     66     /// <summary>
     67     /// 将小怪物进行激活
     68     /// </summary>
     69     private void ActivateMoster()
     70     {
     71         int index = Random.Range(0, mosters.Length);            //取得随机的生成怪物的下标
     72         activateMoster = mosters[index];
     73         activateMoster.SetActive(true);
     74         activateMoster.GetComponent<BoxCollider>().enabled = true;
     75     }
     76 
     77     /// <summary>
     78     /// 将怪物进行隐藏
     79     /// </summary>
     80     private void DeActivateMoster()
     81     {
     82         if(activateMoster!=null)
     83         {
     84             activateMoster.GetComponent<BoxCollider>().enabled = false;
     85             activateMoster.SetActive(false);
     86             activateMoster = null;
     87         }
     88        StartCoroutine(AliveTiemr());
     89 
     90     }
     91 
     92     /// <summary>
     93     /// 当怪物被打死后,让外界(MosterManager)进行调用重新再生成一波敌人
     94     /// </summary>
     95     public void UpdateMoster()
     96     {
     97         StopAllCoroutines();            //现将所有的协程进行暂停,避免出现协程没运行完,就开始生成下一波怪物了
     98         if (activateMoster!=null)
     99         {
    100             activateMoster.GetComponent<BoxCollider>().enabled = false;
    101             activateMoster.SetActive(false);
    102             activateMoster = null;
    103         }
    104         StartCoroutine(AliveTiemr());
    105     }
    106 
    107 
    108     /// <summary>
    109     /// 通过指定的怪物类型来进行怪物的生成
    110     /// 放在游戏加载的时候被调用
    111     /// </summary>
    112     /// <param name="type">怪物下标类型</param>
    113     public void ActivateMonsterByType(int type)
    114     {
    115         StopAllCoroutines();            //先停止所有的协程
    116         if(activateMoster!=null)
    117         {
    118             activateMoster.GetComponent<BoxCollider>().enabled = false;
    119             activateMoster.SetActive(false);
    120             activateMoster = null;          
    121         }
    122         activateMoster = mosters[type];         //通过怪物类型来进行生成
    123         activateMoster.SetActive(true);
    124         activateMoster.GetComponent<BoxCollider>().enabled = true;
    125         StartCoroutine(DeathTimer());           //怪物生成出来了,就要等待被删除了
    126 
    127     }
    128 }

    4、希望可以帮助到大家,这也是自己总结出来的,有错误希望大家帮忙指正。

    【注意:】使用JSON的话要导入Json库!!!

  • 相关阅读:
    一只iPhone的全球之旅
    iOS开发之在地图上绘制出你运行的轨迹
    iOS开发之一些字符串常用的代码
    json格式化和查看工具
    iOS开发之结合asp.net webservice实现文件上传下载
    更改GROOVE的文件夹位置
    调试Windows Service
    从数据库中获取Insert语句
    iOS开发学习笔记(一)
    《影响力》的影响
  • 原文地址:https://www.cnblogs.com/zhh19981104/p/9141070.html
Copyright © 2011-2022 走看看