添加保存按钮

直接在LevelEditor脚本的OnGUI代码块中添加下列代码

1
2
3
4
5
var saveButtonRect = new Rect(Screen.width - 110,Screen.height - 60, 100, 50);
if (GUI.Button(saveButtonRect, "Save", mRightButtonStyle.Value))
{

}

我们需要保存的信息是当前场景物品的位置和名称,首先在LevelEidtor脚本内部新建一个需要保存序列化信息的类

1
2
3
4
5
6
class LevelItemInfo
{
public string Name;
public float X;
public float Y;
}

添加保存逻辑

将保存逻辑都写入之前OnGUI代码块中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
var saveButtonRect = new Rect(Screen.width - 110,Screen.height - 60, 100, 50);
if (GUI.Button(saveButtonRect, "Save", mRightButtonStyle.Value))
{
var infos = new List<LevelItemInfo>(transform.childCount);
foreach (Transform child in transform)
{
infos.Add(new LevelItemInfo()
{
Name = child.name,
X = child.position.x,
Y = child.position.y
});
}
var document = new XmlDocument();
var declaration = document.CreateXmlDeclaration("1.0", "UTF-8","");
document.AppendChild(declaration);

var level = document.CreateElement("Level");
document.AppendChild(level);

foreach (var levelItemInfo in infos)
{
var levelItem = document.CreateElement("LevelItem");
levelItem.SetAttribute("name", levelItemInfo.Name);
levelItem.SetAttribute("x", levelItemInfo.X.ToString());
levelItem.SetAttribute("y", levelItemInfo.Y.ToString());
level.AppendChild(levelItem);
}

//可以用下面的代码输出Xml来查看保存的内容
//Debug.Log(docement.InnerXml);//输出的Xml不带排版,比较杂乱
//或者使用下面的方法
StringBuilder stringBuilder = new StringBuilder();
using(StringWriter stringWriter = new StringWriter(stringBuilder))
{
using(XmlTextWriter xmlTextWriter = new XmlTextWriter(stringWriter))
{
xmlTextWriter.Formatting = Formatting.Indented;
level.WriteTo(xmlTextWriter);
Debug.Log(stringWriter.ToString());
}
}
//观察验证保存内容无误后,删除查看Xml的代码
}

添加数据持久化逻辑

还是和上面一样的位置,我们删除打印Xml的代码,然后修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
if (GUI.Button(saveButtonRect, "Save", mRightButtonStyle.Value))
{
//...

foreach (var levelItemInfo in infos)
{
var levelItem = document.CreateElement("LevelItem");
levelItem.SetAttribute("name", levelItemInfo.Name);
levelItem.SetAttribute("x", levelItemInfo.X.ToString());
levelItem.SetAttribute("y", levelItemInfo.Y.ToString());
level.AppendChild(levelItem);
}

//我们在编辑器环境下保存
#if UNITY_EDITOR
var levelFileFolder = Application.dataPath + "/LevelFiles";
if (!Directory.Exists(levelFileFolder))
{
Directory.CreateDirectory(levelFileFolder);
}

var levelFilePath = levelFileFolder + "/" + DateTime.Now.ToString("yyyyMMddhhmmss") + ".xml";
try
{

document.Save(levelFilePath);
}
catch (Exception ex)
{
Debug.LogError(ex.Message);
}
#endif
}

添加解析逻辑

修改LevelPlayer脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
using System.IO;
using System.Linq;
using System.Xml;
using UnityEngine;

namespace ShootingEditor2D
{
public class LevelPlayer : MonoBehaviour
{
static string mLevelFilesFolder;
private void Awake()
{
mLevelFilesFolder = Application.dataPath + "/LevelFiles";
}
enum State//添加状态,用于进入场景后隐藏GUI
{
Selection,//选择存档阶段
Playing//选择完后游玩阶段
}
private State mCurrentState = State.Selection;
void ParseAndRun(string xml)
{
var document = new XmlDocument();
document.LoadXml(xml);

var levelNode = document.SelectSingleNode("Level");

foreach (XmlElement levelItemNode in levelNode.ChildNodes)
{
var ItemArrtibutes = levelItemNode.Attributes;
var levelItemName = ItemArrtibutes["name"].Value;
var levelItemX = int.Parse(ItemArrtibutes["x"].Value);
var levelItemY = int.Parse(ItemArrtibutes["y"].Value);

var levelItemPrefab = Resources.Load<GameObject>(levelItemName);
var levelItemGameobject = Instantiate(levelItemPrefab, transform);
levelItemGameobject.transform.position = new Vector3(levelItemX, levelItemY, 0);
}
}
private void OnGUI()
{
if(mCurrentState == State.Selection)
{
var filePaths = Directory.GetFiles(mLevelFilesFolder);

int y = 10;//每有一个存档,就多向下绘制一个按钮

foreach (var filePath in filePaths.Where(f => f.EndsWith("xml")))
{
var fileName = Path.GetFileName(filePath);

if (GUI.Button(new Rect(10, y, 100, 40), fileName))//根据场景名字绘制按钮
{
var xml = File.ReadAllText(filePath);
Debug.Log(xml);
ParseAndRun(xml);
mCurrentState = State.Playing;
}

y += 50;
}
}
}
}
}

进入LevelPlayer场景,点击运行后,选择我们保存的场景运行。