本章目标
完成BattleStar的数据存储与性能优化
导入资源文件
文件下载:地址
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中增加如下代码
代码语言:javascript复制using UnityEngine;
using UnityEngine.UI;
public class Player : MonoBehaviour
{
[SerializeField] private Text healthText;
[SerializeField] private GameManager manager;
public GameObject RestTineText;
int time;
AudioSource AS;
int playerHealth = 5;
public int PlayerHealth
{
get { return playerHealth; }
set
{
playerHealth = value;
healthText.text = playerHealth.ToString();
if (playerHealth == 0)
{
PlayerDie();
}
}
}
private void Start()
{
AS = GameObject.Find("Audio Source").GetComponent<AudioSource>();
}
//死亡(游戏结束)
private void PlayerDie()
{
time = int.Parse(RestTineText.GetComponent<Text>().text);
PlayerPrefs.SetInt("RestTime", time);
Debug.Log(PlayerPrefs.GetInt("RestTime"));
manager.GameOver();
}
public void playGetHurt()
{
PlayerHealth--;
AS.clip = (AudioClip)Resources.Load("PlayerGetHurt");
AS.Play();
}
}
我们看到,在玩家死亡时,该代码调用了manager.GameOver()方法。通过Unity找到该代码,我们看到该方法如下
代码语言:javascript复制private bool gameOver;
void Start()
{
gameOver = false;
//锁定鼠标位置并设置为不可见
Cursor.lockState = CursorLockMode.Locked;
Cursor.visible = false;
}
public void GameOver()
{
//如果游戏尚未结束
if (!gameOver)
{
SceneManager.LoadScene("BattleStar_GuideScene");
}
}
因此我们进入BattleStar_GuideScene场景,Menu的List是所有Record的集合,我们给他增添一个代码,用于读取场景切换之前保存在注册表里的数据
代码语言:javascript复制using UnityEngine;
using UnityEngine.UI;
public class ListTime : MonoBehaviour {
public GameObject Timetext;
void Start () {
Timetext.GetComponent<Text>().text = PlayerPrefs.GetInt("RestTime").ToString();
}
}
2、Xml
Xml文件用来存储姓名、成绩等信息,下面展示一种单纯Xml API格式编写的脚本代码,和用LINQ to XML API格式代码
Xml格式
代码语言:javascript复制using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.IO;
using System.Xml;
//实现每次游戏胜利排行榜排序并写入的顺序:1、创建Xml文件—>{2、运行游戏胜利时添加数据到xml文件—>
//3、导出数据到List<Rank>集合(先将List原数据清空),并进行排序—>4、写入排行榜}(每次胜利添加名字时运行一次)
public class Xml_Skode : MonoBehaviour
{
List<Rank> timeRank = new List<Rank>();
public GameObject recordParent;
public Text nameText;
string filepath1, filepath2;
private void Start()
{
filepath1 = Application.dataPath @"myRank_Skode.xml";
filepath2 = @"C:/Users/Administrator/Desktop/myRank_Skode.xml";
CreatXml();
}
//创建Xml文件
void CreatXml()
{
if (!File.Exists(filepath1))
{
XmlDocument xmlDoc = new XmlDocument();
XmlElement userData = xmlDoc.CreateElement("userData");
xmlDoc.AppendChild(userData);
xmlDoc.Save(filepath1);
}
}
XmlDocument xmlDoc = new XmlDocument();
public void UpdateXml_Skode() //添加数据。该方法绑定在取得游戏胜利输入名字的“确定”按键上
{
xmlDoc.Load(filepath1);
XmlNode userData = xmlDoc.SelectSingleNode("userData");
XmlElement rank = xmlDoc.CreateElement("rank");
XmlElement userName = xmlDoc.CreateElement("name");
XmlElement userTime = xmlDoc.CreateElement("time");
userName.InnerText = nameText.text; //InnerText为标签之间的纯文本信息
userTime.InnerText = PlayerPrefs.GetInt("RestTime").ToString();
xmlDoc.AppendChild(userData);
userData.AppendChild(rank);
rank.AppendChild(userName);
rank.AppendChild(userTime);
xmlDoc.Save(filepath1);
outXmlToList();
}
//导出xml数据到List
void outXmlToList()
{
timeRank.Clear(); //因为每次胜利输入名字时都要在timeRank中写入数据,所以要先清空上次留下的数据,再执行本次命令
XmlNodeList userData = xmlDoc.SelectSingleNode("userData").ChildNodes;
string userInfo_Name = null; //用于承载遍历Xml得出的信息,将其写入新的timeRank集合
int userInfo_Time = 0;
foreach (XmlElement rankList in userData) //遍历所有rank节点
{
foreach (XmlElement userInfo in rankList) //遍历每个rank节点下的name、time信息
{
if (userInfo.Name == "name")
{
userInfo_Name = userInfo.InnerText;
}
else //rank节点下一共两个标签,分别是name和time
{
//userInfo_Time = Convert.ToInt32(userInfo.InnerText); //using System;
userInfo_Time = int.Parse(userInfo.InnerText);
}
}
Rank iRank = new Rank(userInfo_Name, userInfo_Time);
timeRank.Add(iRank);
}
TimeSort();
}
//给timeRank中的元素排序
void TimeSort()
{
for (int i = timeRank.Count; i > 1; i--) //循环,不断将最小的数字向后排。10个数字,进行9次排序就够了
{
for (int j = 0; j < i - 1; j ) //本次循环将最小的时间数字排到最后面(前面的数字还是乱的)
{
if (timeRank[j].time < timeRank[j 1].time)
{
Rank temp;
temp = timeRank[j];
timeRank[j] = timeRank[j 1];
timeRank[j 1] = temp;
}
}
}
WriteList();
}
//将成绩写入排行榜
void WriteList()
{
Text noText, nameText, timeText;
if (timeRank.Count > 10)
{
for (int i = 1; i < 11; i )
{
GameObject gObject = GameObject.Find("Record (" i.ToString() ")");
#region 给排名序号赋值
noText = gObject.transform.Find("NumberText").GetComponent<Text>();
if (i < 10)
{
noText.text = 0.ToString() i.ToString();
}
else
noText.text = i.ToString();
#endregion
#region 给Nmae赋值
nameText = gObject.transform.Find("NameText").GetComponent<Text>();
nameText.text = timeRank[i - 1].name;
#endregion
#region 给Time赋值
timeText = gObject.transform.Find("TimeText").GetComponent<Text>();
timeText.text = timeRank[i - 1].time.ToString();
#endregion
}
}
else
{
for (int i = 0; i < timeRank.Count; i ) //i不能等于1,如果等于1,当只有一个成绩时,排行榜就不会显示
{
GameObject gObject = GameObject.Find("Record (" (i 1).ToString() ")");
#region 给排名序号赋值
noText = gObject.transform.Find("NumberText").GetComponent<Text>();
if (i < 9)
{
noText.text = 0.ToString() (i 1).ToString();
}
else
noText.text = (i 1).ToString();
#endregion
#region 给Nmae赋值
nameText = gObject.transform.Find("NameText").GetComponent<Text>();
if (nameText != null)
Debug.Log("find name");
nameText.text = timeRank[i].name;
#endregion
#region 给Time赋值
timeText = gObject.transform.Find("TimeText").GetComponent<Text>();
timeText.text = timeRank[i].time.ToString();
#endregion
}
}
}
}
LINQ to XML API格式
代码语言:javascript复制using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.IO;
using System.Linq;
using System.Xml.Linq;
public class Xml_Skode2 : MonoBehaviour
{
List<Rank> timeRank = new List<Rank>();
public GameObject recordParent;
public Text nameText;
string filepath1, filepath2;
private void Start()
{
filepath1 = Application.dataPath @"myRank_Skode2.xml";
filepath2 = @"C:/Users/Administrator/Desktop/myRank_Skode.xml";
CreatXml();
}
//创建Xml文件
void CreatXml()
{
if (!File.Exists(filepath1))
{
XDocument xDoc = new XDocument(
new XElement("userData"));
xDoc.Save(filepath1);
}
}
public void UpdateXml_Skode() //添加数据。该方法绑定在取得游戏胜利输入名字的“确定”按键上
{
XDocument xDoc = XDocument.Load(filepath1);
XElement userData = xDoc.Element("userData");
userData.Add(new XElement("rank",
new XElement("name", nameText.text),
new XElement("time", PlayerPrefs.GetInt("RestTime").ToString())
)
);
xDoc.Save(filepath1);
outXmlToList();
}
//导出xml数据到List
void outXmlToList()
{
timeRank.Clear();
XDocument xDoc = XDocument.Load(filepath1);
IEnumerable<XElement> userData = xDoc.Element("userData").Elements();
string userInfo_Name = null;
int userInfo_Time = 0;
var rankList = from a in userData
select a;
foreach (var b in rankList) //rank层
{
foreach (var c in b.Elements()) //name、time层
{
if (c.Name == "name")
{
userInfo_Name = c.Value;
}
else
{
userInfo_Time = int.Parse(c.Value);
}
}
Rank iRank = new Rank(userInfo_Name, userInfo_Time);
timeRank.Add(iRank);
}
TimeSort();
}
//给timeRank中的元素排序
void TimeSort()
{
for (int i = timeRank.Count; i > 1; i--)
{
for (int j = 0; j < i - 1; j )
{
if (timeRank[j].time < timeRank[j 1].time)
{
Rank temp;
temp = timeRank[j];
timeRank[j] = timeRank[j 1];
timeRank[j 1] = temp;
}
}
}
WriteList();
}
//将成绩写入排行榜
void WriteList()
{
Text noText, nameText, timeText;
if (timeRank.Count > 10)
{
for (int i = 1; i < 11; i )
{
GameObject gObject = GameObject.Find("Record (" i.ToString() ")");
#region 给排名序号赋值
noText = gObject.transform.Find("NumberText").GetComponent<Text>();
if (i < 10)
{
noText.text = 0.ToString() i.ToString();
}
else
noText.text = i.ToString();
#endregion
#region 给Nmae赋值
nameText = gObject.transform.Find("NameText").GetComponent<Text>();
nameText.text = timeRank[i - 1].name;
#endregion
#region 给Time赋值
timeText = gObject.transform.Find("TimeText").GetComponent<Text>();
timeText.text = timeRank[i - 1].time.ToString();
#endregion
}
}
else
{
for (int i = 0; i < timeRank.Count; i )
{
GameObject gObject = GameObject.Find("Record (" (i 1).ToString() ")");
#region 给排名序号赋值
noText = gObject.transform.Find("NumberText").GetComponent<Text>();
if (i < 9)
{
noText.text = 0.ToString() (i 1).ToString();
}
else
noText.text = (i 1).ToString();
#endregion
#region 给Nmae赋值
nameText = gObject.transform.Find("NameText").GetComponent<Text>();
if (nameText != null)
Debug.Log("find name");
nameText.text = timeRank[i].name;
#endregion
#region 给Time赋值
timeText = gObject.transform.Find("TimeText").GetComponent<Text>();
timeText.text = timeRank[i].time.ToString();
#endregion
}
}
}
}