SIKI_Unity_2_入门_通过实例学习游戏的存档和读档
任务5:创建设计目标
Animation的直接使用:
将Animation组件直接挂载在游戏物体上即可播放
脚本控制:
方法1:
直接在Inspector面板给Animation的Animations集合赋值动画a和b
通过animation.clip = a或animation.clip = b后进行animation.Play()即可播放相关动画
注意:这种情况下如果在Inspector面板的Animations集合中没有动画b,那么即使给animation.clip = b赋了b动画的值,也是无法播放b动画的
[SerializeField]
private AnimationClip m_IdleAnimationClip;
[SerializeField]
private AnimationClip m_DieAnimationClip;
m_Animation.clip = m_DieAnimationClip;
m_Animation.Play();
方法2:
用代码给Animation的Animations赋值,AddClip(clip, name)可以给音效设定名称,之后animation.Play(name)传入name即可播放对应音效
[SerializeField]
private AnimationClip m_IdleAnimationClip;
[SerializeField]
private AnimationClip m_IdleAnimationClip;
m_Animation.AddClip(m_IdleAnimationClip, "Idle");
m_Animation.AddClip(m_DieAnimationClip, "Die");
m_Animation.Play("Die");
任务9:设置手枪的旋转
效果:
思路:
设定旋转的最大与最小角度,并根据鼠标在屏幕上的位置,按比例对枪体进行x和y轴上的旋转
任务21:存档相关概念
unity中使用的存档方式
1. PlayerPrefs: 数据持久化方案
存储形式: 键值对
存储数据: Int、Float、String类型
bool类型可以用int的0/1模拟
接口:
PlayerPrefs.SetInt("Key", value);
PlayerPrefs.SetFloat("Key", value);
PlayerPrefs.SetString("Key", value);
PlayerPrefs.GetInt("Key");
2. Serialization/ Deserialization: 序列化和反序列化
存储: 将对象序列化为字节流(Bytes),将字节流存储
读取: 将存储的字节流数据反序列化为对象
常见的数据序列化方法:二进制、XML、JSON
简单的数据用二进制的方式存储就够了,但是二进制的方式有局限性
在实际开发中最常用的是XML/ JSON方式
二进制方法:Binary Formatter
序列化:新建/打开一个二进制文件,通过二进制格式器将对象写入该二进制文件
反序列化:打开待反序列化的二进制文件,通过二进制格式器将文件解析成对象
XML:扩展标记语言(具有结构性的标记语言)
序列化/ 反序列化的方式与二进制方法类似
JSON:数据的常用格式,可用来跨平台数据传输
序列化: 对象 -- > JSON
反序列化: JSON -> 对象
优缺点:
二进制: 简单 || 可读性差
XML: 可读性强 || 数据文件比较大、冗余信息多
JSON: 数据格式较简单、易读写 || 可读性比XML差(键值对--不直观)
任务23:存储背景音乐的开关状态
使用PlayerPrefs保存后,需要通过PlayerPrefs.Save()进行存储
任务27~28:通过二进制方法存档读档
Save对象中包含相关数据作为属性,该类需要marked as Serializable
[Serializable]
public class SaveData
{
public List<Enemy.EnemyType> enemyTypeList; // 对应位置的敌人种类信息
public SaveData() {
enemyTypeList = new List<Enemy.EnemyType>();
for(int i = 0; i < GameManager.instance.enemyGeneratorList.Count; i++) {
enemyTypeList.Add(Enemy.EnemyType.Null);
}
}
public int shootCount;
public int score;
}
存储:
void SaveByBinary() {
BinaryFormatter bf = new BinaryFormatter();
FileStream fileStream = File.Create(Application.dataPath + "/StreamingFile/ByBin.txt");
bf.Serialize(fileStream, save);
fileStream.Close();
}
读取:
void LoadByBinary() {
BinaryFormatter bf = new BinaryFormatter();
FileStream fileStream = File.Open(Application.dataPath + "StreamingFile/ByBin.txt");
Save save = (Save) bf.Deserialize(fileStream);
fileStream.Close();
}
存储得到的二进制文件:
FAssembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null SaveData
enemyTypeList
shootCountscore |System.Collections.Generic.List`1[[Enemy+EnemyType, Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]] |System.Collections.Generic.List`1[[Enemy+EnemyType, Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]] _items_size_version Enemy+EnemyType[] Enemy+EnemyType ?Enemy+EnemyType value__ ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ??
任务29~30:通过Json方法存档读档
通过第三方插件LitJson来操作Json文件
存档:
void SaveByJson(SaveData save) {
string jsonRepresentation = JsonUtility.ToJson(save);
StreamWriter streamWriter = new StreamWriter(Application.dataPath + "...");
streamWriter.Write(jsonRepresentation);
streamWriter.Close();
}
读档:
SaveData LoadByJson() {
StreamReader streamReader = new StreamReader(Application.dataPath + "");
string jsonRepresentation = streamReader.ReadToEnd();
streamReader.Close();
return JsonUtility.FromJson<SaveData>(jsonRepresentation);
}
或者使用JsonMapper.ToObject<SaveData>(jsonRepresentation);
存储得到的Json文件:
{"enemyTypeList":[1,0,4,4,4,1,0,3,4],"shootCount":4,"score":0}
任务31~32:通过XML方法存档读档
通过System.Xml的接口进行Xml文件的操作
存档:
private void SaveByXML(SaveData save) {
// 创建XML文档
XmlDocument xmlDocument = new XmlDocument();
// 创建根节点
XmlElement root = xmlDocument.CreateElement("root");
root.SetAttribute("name", "save1"); // 节点的属性值
xmlDocument.AppendChild(root);
// 怪物信息
XmlElement target;
for (int i = 0; i < save.enemyTypeList.Count; i++) {
target = xmlDocument.CreateElement("target");
target.InnerText = ((int)save.enemyTypeList[i]).ToString();
root.AppendChild(target);
}
// 分数信息
XmlElement scoreElement = xmlDocument.CreateElement("score");
scoreElement.InnerText = save.score.ToString();
root.AppendChild(scoreElement);
XmlElement shootCountElement = xmlDocument.CreateElement("shootNumber");
shootCountElement.InnerText = save.shootCount.ToString();
root.AppendChild(shootCountElement);
xmlDocument.Save(m_SavePath + BY_XML_FILENAME);
}
读档:
private SaveData LoadByXML() {
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.Load(m_SavePath + BY_XML_FILENAME);
SaveData save = new SaveData();
XmlNodeList targetNodeList = xmlDocument.GetElementsByTagName("target");
// 读取敌人信息
for (int i = 0; i < targetNodeList.Count; i++) {
save.enemyTypeList[i] = ((Enemy.EnemyType)int.Parse(targetNodeList[i].InnerText));
}
XmlNode scoreNode = xmlDocument.GetElementsByTagName("score")[0];
save.score = int.Parse(scoreNode.InnerText);
XmlNode shootCountNode = xmlDocument.GetElementsByTagName("shootCount")[0];
save.shootCount = int.Parse(shootCountNode.InnerText);
return save;
}
存储得到的Xml文件:
<root name="save1">
<target>4</target>
<target>4</target>
<target>4</target>
<target>4</target>
<target>3</target>
<target>3</target>
<target>3</target>
<target>4</target>
<target>3</target>
<score>0</score>
<shootCount>3</shootCount>
</root>