设为首页收藏本站
查看: 426|回复: 0

Unity-BattleStar丨12.0 让数据更流畅:数据存储与性能优化

[复制链接]

该用户从未签到

17

主题

19

帖子

447

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
447
橙子va 发表于 2018-6-18 01:59:28 4260 | 显示全部楼层 |阅读模式
本章目标

完成BattleStar的数据存储与性能优化

效果展示:

0618-02.gif


导入资源文件

文件下载:地址

1、导入Package

2、运行_Scenes里面的BattleStar_GameScene场景,观察


BattleStar的数据存储

将BattleStar_GuideScene加载到build settings里,否则运行时会出现无法切换场景的现象。

Debug描述如下:

Scene 'BattleStar_GuideScene' couldn't be loaded because it has not been added to the build settings or the AssetBundle has not been loaded.

To add a scene to the build settings use the menu File->Build Settings...


1、PlayerPrefs

由于在场景切换的时候,脚本内的参数会被重置的,因此需要将玩家在游戏中剩余时间以某种方式保存起来,并传输到下一场景。在这个过程中,我们用PlayerPrefs完成游戏过程中游戏分数的数据存储功能

在Player中增加如下代码

  1. using UnityEngine;
  2. using UnityEngine.UI;

  3. public class Player : MonoBehaviour
  4. {
  5.     [SerializeField] private Text healthText;
  6.     [SerializeField] private GameManager manager;

  7.     public GameObject RestTineText;

  8.     int time;

  9.     AudioSource AS;

  10.     int playerHealth = 5;

  11.     public int PlayerHealth
  12.     {
  13.         get { return playerHealth; }
  14.         set
  15.         {
  16.             playerHealth = value;

  17.             healthText.text = playerHealth.ToString();

  18.             if (playerHealth == 0)
  19.             {
  20.                 PlayerDie();
  21.             }
  22.         }
  23.     }

  24.     private void Start()
  25.     {
  26.         AS = GameObject.Find("Audio Source").GetComponent<AudioSource>();
  27.     }

  28.     //死亡(游戏结束)
  29.     private void PlayerDie()
  30.     {
  31.         time = int.Parse(RestTineText.GetComponent<Text>().text);
  32.         PlayerPrefs.SetInt("RestTime", time);
  33.         Debug.Log(PlayerPrefs.GetInt("RestTime"));
  34.         manager.GameOver();
  35.     }

  36.     public void playGetHurt()
  37.     {
  38.         PlayerHealth--;
  39.         AS.clip = (AudioClip)Resources.Load("PlayerGetHurt");
  40.         AS.Play();
  41.     }
  42. }
复制代码

我们看到,在玩家死亡时,该代码调用了manager.GameOver()方法。通过Unity找到该代码,我们看到该方法如下

  1. private bool gameOver;

  2.     void Start()
  3.     {
  4.         gameOver = false;

  5.         //锁定鼠标位置并设置为不可见
  6.         Cursor.lockState = CursorLockMode.Locked;
  7.         Cursor.visible = false;
  8.     }
  9.    
  10.     public void GameOver()
  11.     {
  12.         //如果游戏尚未结束
  13.         if (!gameOver)
  14.         {
  15.             SceneManager.LoadScene("BattleStar_GuideScene");
  16.         }
  17.     }
复制代码

因此我们进入BattleStar_GuideScene场景,Menu的List是所有Record的集合,我们给他增添一个代码,用于读取场景切换之前保存在注册表里的数据

  1. using UnityEngine;
  2. using UnityEngine.UI;

  3. public class ListTime : MonoBehaviour {

  4.     public GameObject Timetext;
  5.    
  6.         void Start () {
  7.         Timetext.GetComponent<Text>().text = PlayerPrefs.GetInt("RestTime").ToString();
  8.     }
  9. }
复制代码

2、Xml

Xml文件用来存储姓名、成绩等信息,下面展示一种单纯Xml API格式编写的脚本代码,和用LINQ to XML API格式代码

Xml格式
  1. using System.Collections.Generic;
  2. using UnityEngine;
  3. using UnityEngine.UI;
  4. using System.IO;
  5. using System.Xml;

  6. //实现每次游戏胜利排行榜排序并写入的顺序:1、创建Xml文件—>{2、运行游戏胜利时添加数据到xml文件—>
  7. //3、导出数据到List<Rank>集合(先将List原数据清空),并进行排序—>4、写入排行榜}(每次胜利添加名字时运行一次)

  8. public class Xml_Skode : MonoBehaviour
  9. {
  10.     List<Rank> timeRank = new List<Rank>();
  11.     public GameObject recordParent;
  12.     public Text nameText;
  13.     string filepath1, filepath2;

  14.     private void Start()
  15.     {
  16.         filepath1 = Application.dataPath + @"\myRank_Skode.xml";
  17.         filepath2 = @"C:/Users/Administrator/Desktop/myRank_Skode.xml";
  18.         CreatXml();
  19.     }

  20.     //创建Xml文件
  21.     void CreatXml()
  22.     {
  23.         if (!File.Exists(filepath1))
  24.         {
  25.             XmlDocument xmlDoc = new XmlDocument();
  26.             XmlElement userData = xmlDoc.CreateElement("userData");
  27.             xmlDoc.AppendChild(userData);

  28.             xmlDoc.Save(filepath1);
  29.         }
  30.     }

  31.     XmlDocument xmlDoc = new XmlDocument();

  32.     public void UpdateXml_Skode()  //添加数据。该方法绑定在取得游戏胜利输入名字的“确定”按键上
  33.     {
  34.         xmlDoc.Load(filepath1);
  35.         XmlNode userData = xmlDoc.SelectSingleNode("userData");
  36.         XmlElement rank = xmlDoc.CreateElement("rank");
  37.         XmlElement userName = xmlDoc.CreateElement("name");
  38.         XmlElement userTime = xmlDoc.CreateElement("time");

  39.         userName.InnerText = nameText.text;   //InnerText为标签之间的纯文本信息
  40.         userTime.InnerText = PlayerPrefs.GetInt("RestTime").ToString();

  41.         xmlDoc.AppendChild(userData);
  42.         userData.AppendChild(rank);
  43.         rank.AppendChild(userName);
  44.         rank.AppendChild(userTime);

  45.         xmlDoc.Save(filepath1);

  46.         outXmlToList();
  47.     }

  48.     //导出xml数据到List
  49.     void outXmlToList()
  50.     {
  51.         timeRank.Clear();  //因为每次胜利输入名字时都要在timeRank中写入数据,所以要先清空上次留下的数据,再执行本次命令

  52.         XmlNodeList userData = xmlDoc.SelectSingleNode("userData").ChildNodes;

  53.         string userInfo_Name = null;   //用于承载遍历Xml得出的信息,将其写入新的timeRank集合
  54.         int userInfo_Time = 0;

  55.         foreach (XmlElement rankList in userData)  //遍历所有rank节点
  56.         {
  57.             foreach (XmlElement userInfo in rankList)  //遍历每个rank节点下的name、time信息
  58.             {
  59.                 if (userInfo.Name == "name")
  60.                 {
  61.                     userInfo_Name = userInfo.InnerText;
  62.                 }
  63.                 else    //rank节点下一共两个标签,分别是name和time
  64.                 {
  65.                     //userInfo_Time = Convert.ToInt32(userInfo.InnerText);   //using System;
  66.                     userInfo_Time = int.Parse(userInfo.InnerText);
  67.                 }
  68.             }
  69.             Rank iRank = new Rank(userInfo_Name, userInfo_Time);
  70.             timeRank.Add(iRank);
  71.         }
  72.         TimeSort();
  73.     }


  74.     //给timeRank中的元素排序
  75.     void TimeSort()
  76.     {
  77.         for (int i = timeRank.Count; i > 1; i--)  //循环,不断将最小的数字向后排。10个数字,进行9次排序就够了
  78.         {
  79.             for (int j = 0; j < i - 1; j++)   //本次循环将最小的时间数字排到最后面(前面的数字还是乱的)
  80.             {
  81.                 if (timeRank[j].time < timeRank[j + 1].time)
  82.                 {
  83.                     Rank temp;

  84.                     temp = timeRank[j];
  85.                     timeRank[j] = timeRank[j + 1];
  86.                     timeRank[j + 1] = temp;
  87.                 }
  88.             }
  89.         }

  90.         WriteList();
  91.     }

  92.     //将成绩写入排行榜
  93.     void WriteList()
  94.     {
  95.         Text noText, nameText, timeText;

  96.         if (timeRank.Count > 10)
  97.         {
  98.             for (int i = 1; i < 11; i++)
  99.             {
  100.                 GameObject gObject = GameObject.Find("Record (" + i.ToString() + ")");

  101.                 #region  给排名序号赋值
  102.                 noText = gObject.transform.Find("NumberText").GetComponent<Text>();
  103.                 if (i < 10)
  104.                 {
  105.                     noText.text = 0.ToString() + i.ToString();
  106.                 }
  107.                 else
  108.                     noText.text = i.ToString();
  109.                 #endregion

  110.                 #region 给Nmae赋值
  111.                 nameText = gObject.transform.Find("NameText").GetComponent<Text>();
  112.                 nameText.text = timeRank[i - 1].name;
  113.                 #endregion

  114.                 #region 给Time赋值
  115.                 timeText = gObject.transform.Find("TimeText").GetComponent<Text>();
  116.                 timeText.text = timeRank[i - 1].time.ToString();
  117.                 #endregion
  118.             }
  119.         }
  120.         else
  121.         {
  122.             for (int i = 0; i < timeRank.Count; i++)  //i不能等于1,如果等于1,当只有一个成绩时,排行榜就不会显示
  123.             {
  124.                 GameObject gObject = GameObject.Find("Record (" + (i+1).ToString() + ")");

  125.                 #region  给排名序号赋值
  126.                 noText = gObject.transform.Find("NumberText").GetComponent<Text>();
  127.                 if (i < 9)
  128.                 {
  129.                     noText.text = 0.ToString() + (i+1).ToString();
  130.                 }
  131.                 else
  132.                     noText.text = (i + 1).ToString();
  133.                 #endregion

  134.                 #region 给Nmae赋值
  135.                 nameText = gObject.transform.Find("NameText").GetComponent<Text>();
  136.                 if (nameText != null)
  137.                     Debug.Log("find name");
  138.                 nameText.text = timeRank[i].name;
  139.                 #endregion

  140.                 #region 给Time赋值
  141.                 timeText = gObject.transform.Find("TimeText").GetComponent<Text>();
  142.                 timeText.text = timeRank[i].time.ToString();
  143.                 #endregion
  144.             }
  145.         }
  146.     }
  147. }
复制代码


LINQ to XML API格式
  1. using System.Collections.Generic;
  2. using UnityEngine;
  3. using UnityEngine.UI;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Xml.Linq;

  7. public class Xml_Skode2 : MonoBehaviour
  8. {
  9.     List<Rank> timeRank = new List<Rank>();
  10.     public GameObject recordParent;
  11.     public Text nameText;
  12.     string filepath1, filepath2;

  13.     private void Start()
  14.     {
  15.         filepath1 = Application.dataPath + @"\myRank_Skode2.xml";
  16.         filepath2 = @"C:/Users/Administrator/Desktop/myRank_Skode.xml";
  17.         CreatXml();
  18.     }

  19.     //创建Xml文件
  20.     void CreatXml()
  21.     {
  22.         if (!File.Exists(filepath1))
  23.         {
  24.             XDocument xDoc = new XDocument(
  25.                 new XElement("userData"));
  26.             xDoc.Save(filepath1);
  27.         }
  28.     }

  29.     public void UpdateXml_Skode()  //添加数据。该方法绑定在取得游戏胜利输入名字的“确定”按键上
  30.     {
  31.         XDocument xDoc = XDocument.Load(filepath1);
  32.         XElement userData = xDoc.Element("userData");
  33.         userData.Add(new XElement("rank",
  34.             new XElement("name", nameText.text),
  35.             new XElement("time", PlayerPrefs.GetInt("RestTime").ToString())
  36.             )
  37.             );

  38.         xDoc.Save(filepath1);

  39.         outXmlToList();
  40.     }

  41.     //导出xml数据到List
  42.     void outXmlToList()
  43.     {
  44.         timeRank.Clear();

  45.         XDocument xDoc = XDocument.Load(filepath1);
  46.         IEnumerable<XElement> userData = xDoc.Element("userData").Elements();

  47.         string userInfo_Name = null;
  48.         int userInfo_Time = 0;

  49.         var rankList = from a in userData
  50.                        select a;

  51.         foreach (var b in rankList)  //rank层
  52.         {
  53.             foreach (var c in b.Elements())   //name、time层
  54.             {
  55.                 if (c.Name == "name")
  56.                 {
  57.                     userInfo_Name = c.Value;
  58.                 }
  59.                 else
  60.                 {
  61.                     userInfo_Time = int.Parse(c.Value);
  62.                 }
  63.             }

  64.             Rank iRank = new Rank(userInfo_Name, userInfo_Time);
  65.             timeRank.Add(iRank);
  66.         }
  67.         TimeSort();
  68.     }


  69.     //给timeRank中的元素排序
  70.     void TimeSort()
  71.     {
  72.         for (int i = timeRank.Count; i > 1; i--)
  73.         {
  74.             for (int j = 0; j < i - 1; j++)
  75.             {
  76.                 if (timeRank[j].time < timeRank[j + 1].time)
  77.                 {
  78.                     Rank temp;

  79.                     temp = timeRank[j];
  80.                     timeRank[j] = timeRank[j + 1];
  81.                     timeRank[j + 1] = temp;
  82.                 }
  83.             }
  84.         }

  85.         WriteList();
  86.     }

  87.     //将成绩写入排行榜
  88.     void WriteList()
  89.     {
  90.         Text noText, nameText, timeText;

  91.         if (timeRank.Count > 10)
  92.         {
  93.             for (int i = 1; i < 11; i++)
  94.             {
  95.                 GameObject gObject = GameObject.Find("Record (" + i.ToString() + ")");

  96.                 #region  给排名序号赋值
  97.                 noText = gObject.transform.Find("NumberText").GetComponent<Text>();
  98.                 if (i < 10)
  99.                 {
  100.                     noText.text = 0.ToString() + i.ToString();
  101.                 }
  102.                 else
  103.                     noText.text = i.ToString();
  104.                 #endregion

  105.                 #region 给Nmae赋值
  106.                 nameText = gObject.transform.Find("NameText").GetComponent<Text>();
  107.                 nameText.text = timeRank[i - 1].name;
  108.                 #endregion

  109.                 #region 给Time赋值
  110.                 timeText = gObject.transform.Find("TimeText").GetComponent<Text>();
  111.                 timeText.text = timeRank[i - 1].time.ToString();
  112.                 #endregion
  113.             }
  114.         }
  115.         else
  116.         {
  117.             for (int i = 0; i < timeRank.Count; i++)
  118.             {
  119.                 GameObject gObject = GameObject.Find("Record (" + (i + 1).ToString() + ")");

  120.                 #region  给排名序号赋值
  121.                 noText = gObject.transform.Find("NumberText").GetComponent<Text>();
  122.                 if (i < 9)
  123.                 {
  124.                     noText.text = 0.ToString() + (i + 1).ToString();
  125.                 }
  126.                 else
  127.                     noText.text = (i + 1).ToString();
  128.                 #endregion

  129.                 #region 给Nmae赋值
  130.                 nameText = gObject.transform.Find("NameText").GetComponent<Text>();
  131.                 if (nameText != null)
  132.                     Debug.Log("find name");
  133.                 nameText.text = timeRank[i].name;
  134.                 #endregion

  135.                 #region 给Time赋值
  136.                 timeText = gObject.transform.Find("TimeText").GetComponent<Text>();
  137.                 timeText.text = timeRank[i].time.ToString();
  138.                 #endregion
  139.             }
  140.         }
  141.     }
  142. }
复制代码


回复

使用道具 举报

0条回复
跳转到指定楼层

发表回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|赛隆网 ( 粤ICP备16067842号 )  

Copyright 2013 -̳ Ȩ All Rights Reserved.

Powered by Cylonspace ; All Rights Reserved.

QQ|Archiver|手机版|小黑屋|赛隆网 ( 粤ICP备16067842号 )  

GMT+8, 2018-10-21 21:06 , Processed in 0.125024 second(s), 27 queries.

快速回复 返回顶部 返回列表