【unity】將場景導出XML或JSON或二進制而且解析還原場景

http://www.xuanyusong.com/archives/1919node

        導出Unity場景的全部遊戲對象信息,一種是XML一種是JSON。本篇文章咱們把遊戲場景中游戲對象的、旋轉、縮放、平移與Prefab的名稱導出在XML與JSON中。而後解析剛剛導出的XML或JSON經過腳本把導出的遊戲場景還原。在Unity官網上下載隨便下載一個demo Project,以下圖所示這是我剛剛在官網上下載的一個範例程序。json

wKiom1RIrJ7hRpJkAAKE8aHHgRM579.jpg

          接着將層次視圖中的全部遊戲對象都封裝成Prefab保存在資源路徑中,這裏注意一下若是你的Prefab綁定的腳本中有public Object 的話 ,須要在代碼中改一下。。用 Find() FindTag()這類方法在腳本中Awake()方法中來拿,否則Prefab動態加載的時候沒法賦值的,以下圖所示,我把封裝的Prefab對象都放在了Resources/Prefab文件夾下。app

wKiom1RIrJ6Sm5QLAABgRrfLISA098.jpg

OK,如今咱們就須要編寫咱們的導出工具、在Project視圖中建立Editor文件夾,接着建立腳本MyEditor 。以下圖所示。ide

wKioL1RIrOzyZwkhAABIwa2YFMo422.jpg

由於編輯的遊戲場景數量比較多,導出的時候咱們須要遍歷全部的遊戲場景,一個一個的讀取場景信息。而後取得遊戲場景中全部遊戲對象的Prefab的 名稱 旋轉 縮放 平移。有關XML的使用請你們看個人上一篇文章: Unity3D研究院之使用 C#合成解析XML與JSON(四十一) 代碼中我只註釋重點的部分,嘿嘿。工具

 MyEditor.csoop

C#學習

1測試

2ui

3this

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

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

using UnityEngine;

using System.Collections;

using UnityEditor;

using System.Collections.Generic;

using System.Xml;

using System.IO;

using System.Text;

using LitJson;

public class MyEditor : Editor

{

//將全部遊戲場景導出爲XML格式

[MenuItem ("GameObject/ExportXML")]

static void ExportXML ()

{

    string filepath = Application.dataPath + @"/StreamingAssets/my.xml";

if(!File.Exists (filepath))

{

File.Delete(filepath);

}

XmlDocument xmlDoc = new XmlDocument();

XmlElement root = xmlDoc.CreateElement("gameObjects");

//遍歷全部的遊戲場景

foreach (UnityEditor.EditorBuildSettingsScene S in UnityEditor.EditorBuildSettings.scenes)

        {

         //當關卡啓用

            if (S.enabled)

            {

             //獲得關卡的名稱

                string name = S.path;

                //打開這個關卡

EditorApplication.OpenScene(name);

XmlElement scenes = xmlDoc.CreateElement("scenes");

        scenes.SetAttribute("name",name);

foreach (GameObject obj in Object.FindObjectsOfType(typeof(GameObject)))

{

     if (obj.transform.parent == null)

     {

XmlElement gameObject = xmlDoc.CreateElement("gameObjects");

gameObject.SetAttribute("name",obj.name);

 

gameObject.SetAttribute("asset",obj.name + ".prefab");

XmlElement transform = xmlDoc.CreateElement("transform");

XmlElement position = xmlDoc.CreateElement("position");

XmlElement position_x = xmlDoc.CreateElement("x");

position_x.InnerText = obj.transform.position.x+"";

   XmlElement position_y = xmlDoc.CreateElement("y");

position_y.InnerText = obj.transform.position.y+"";

XmlElement position_z = xmlDoc.CreateElement("z");

position_z.InnerText = obj.transform.position.z+"";

position.AppendChild(position_x);

position.AppendChild(position_y);

position.AppendChild(position_z);

 

XmlElement rotation = xmlDoc.CreateElement("rotation");

XmlElement rotation_x = xmlDoc.CreateElement("x");

rotation_x.InnerText = obj.transform.rotation.eulerAngles.x+"";

   XmlElement rotation_y = xmlDoc.CreateElement("y");

rotation_y.InnerText = obj.transform.rotation.eulerAngles.y+"";

XmlElement rotation_z = xmlDoc.CreateElement("z");

rotation_z.InnerText = obj.transform.rotation.eulerAngles.z+"";

rotation.AppendChild(rotation_x);

rotation.AppendChild(rotation_y);

rotation.AppendChild(rotation_z);

 

XmlElement scale = xmlDoc.CreateElement("scale");

XmlElement scale_x = xmlDoc.CreateElement("x");

scale_x.InnerText = obj.transform.localScale.x+"";

   XmlElement scale_y = xmlDoc.CreateElement("y");

scale_y.InnerText = obj.transform.localScale.y+"";

XmlElement scale_z = xmlDoc.CreateElement("z");

scale_z.InnerText = obj.transform.localScale.z+"";

 

scale.AppendChild(scale_x);

scale.AppendChild(scale_y);

scale.AppendChild(scale_z);

 

transform.AppendChild(position);

transform.AppendChild(rotation);

transform.AppendChild(scale);

 

gameObject.AppendChild(transform);

     scenes.AppendChild(gameObject);

root.AppendChild(scenes);

         xmlDoc.AppendChild(root);

         xmlDoc.Save(filepath);

 

     }

}

            }

        }

        //刷新Project視圖, 否則須要手動刷新哦

AssetDatabase.Refresh();

}

 

//將全部遊戲場景導出爲JSON格式

[MenuItem ("GameObject/ExportJSON")]

static void ExportJSON ()

{

string filepath = Application.dataPath + @"/StreamingAssets/json.txt";

       FileInfo t = new FileInfo(filepath);

if(!File.Exists (filepath))

{

File.Delete(filepath);

}

        StreamWriter sw = t.CreateText();

 

StringBuilder sb = new StringBuilder ();

        JsonWriter writer = new JsonWriter (sb);

writer.WriteObjectStart ();

writer.WritePropertyName ("GameObjects");

writer.WriteArrayStart ();

 

foreach (UnityEditor.EditorBuildSettingsScene S in UnityEditor.EditorBuildSettings.scenes)

        {

            if (S.enabled)

            {

                string name = S.path;

EditorApplication.OpenScene(name);

writer.WriteObjectStart();

writer.WritePropertyName("scenes");

writer.WriteArrayStart ();

writer.WriteObjectStart();

writer.WritePropertyName("name");

writer.Write(name);

writer.WritePropertyName("gameObject");

writer.WriteArrayStart ();

 

foreach (GameObject obj in Object.FindObjectsOfType(typeof(GameObject)))

{

     if (obj.transform.parent == null)

     {

writer.WriteObjectStart();

writer.WritePropertyName("name");

writer.Write(obj.name);

 

writer.WritePropertyName("position");

        writer.WriteArrayStart ();

writer.WriteObjectStart();

writer.WritePropertyName("x");

writer.Write(obj.transform.position.x.ToString("F5"));

writer.WritePropertyName("y");

writer.Write(obj.transform.position.y.ToString("F5"));

writer.WritePropertyName("z");

writer.Write(obj.transform.position.z.ToString("F5"));

writer.WriteObjectEnd();

writer.WriteArrayEnd();

 

writer.WritePropertyName("rotation");

        writer.WriteArrayStart ();

writer.WriteObjectStart();

writer.WritePropertyName("x");

writer.Write(obj.transform.rotation.eulerAngles.x.ToString("F5"));

writer.WritePropertyName("y");

writer.Write(obj.transform.rotation.eulerAngles.y.ToString("F5"));

writer.WritePropertyName("z");

writer.Write(obj.transform.rotation.eulerAngles.z.ToString("F5"));

writer.WriteObjectEnd();

writer.WriteArrayEnd();

 

writer.WritePropertyName("scale");

        writer.WriteArrayStart ();

writer.WriteObjectStart();

writer.WritePropertyName("x");

writer.Write(obj.transform.localScale.x.ToString("F5"));

writer.WritePropertyName("y");

writer.Write(obj.transform.localScale.y.ToString("F5"));

writer.WritePropertyName("z");

writer.Write(obj.transform.localScale.z.ToString("F5"));

writer.WriteObjectEnd();

writer.WriteArrayEnd();

 

writer.WriteObjectEnd();

}

}

 

writer.WriteArrayEnd();

writer.WriteObjectEnd();

writer.WriteArrayEnd();

writer.WriteObjectEnd();

}

}

writer.WriteArrayEnd();

writer.WriteObjectEnd ();

 

sw.WriteLine(sb.ToString());

        sw.Close();

        sw.Dispose();

AssetDatabase.Refresh();

}

}

 

OK。此時咱們就能夠導出遊戲場景的信息拉,注意遊戲場景的須要如今Project Setting 中註冊。點擊 GameObject – > Export    XML 和 GameObject – > ExportJson 菜單項便可開始生成。

wKiom1RIrKGBOrn-AAFcRVV0ZTY022.jpg

以下圖所示,場景導出完畢後,會將xml 與Json 文件保存在StreamingAssets路徑下,放在這裏的緣由是方便移動平臺移植,由於它們屬於二進制文件,移動平臺在讀取二進制文件的路徑是不同的。必定要放在這裏喔。

wKioL1RIrPDDt773AAAgb126NFc131.jpg

接着,我繼續建立兩個遊戲場景,一個用來解析XML的場景,一個用來解析JSON的場景。 

XML場景中,建立一個空的遊戲對象,把XML.cs掛上去。

C#

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

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

using UnityEngine;

using System.Collections;

using System.Xml;

using System.IO;

public class XML : MonoBehaviour {

 

// Use this for initialization

void Start ()

{

 

//電腦和iphong上的路徑是不同的,這裏用標籤判斷一下。

#if UNITY_EDITOR

string filepath = Application.dataPath +"/StreamingAssets"+"/my.xml";

#elif UNITY_IPHONE

  string filepath = Application.dataPath +"/Raw"+"/my.xml";

#endif

        //若是文件存在話開始解析。

if(File.Exists (filepath))

{

XmlDocument xmlDoc = new XmlDocument();

xmlDoc.Load(filepath);

XmlNodeList nodeList=xmlDoc.SelectSingleNode("gameObjects").ChildNodes;

foreach(XmlElement scene  in nodeList)

{

//由於個人XML是把全部遊戲對象所有導出, 因此這裏判斷一下只解析須要的場景中的遊戲對象

//JSON和它的原理相似

if(!scene.GetAttribute("name").Equals("Assets/StarTrooper.unity"))

{

continue;

}

 

foreach(XmlElement gameObjects in scene.ChildNodes)

{

 

string asset = "Prefab/" + gameObjects.GetAttribute("name");

Vector3 pos = Vector3.zero;

Vector3 rot = Vector3.zero;

Vector3 sca = Vector3.zero;

foreach(XmlElement transform in gameObjects.ChildNodes)

{

foreach(XmlElement prs in transform.ChildNodes)

{

if(prs.Name == "position")

{

foreach(XmlElement position in prs.ChildNodes)

{

switch(position.Name)

{

case "x":

pos.x = float.Parse(position.InnerText);

break;

case "y":

pos.y = float.Parse(position.InnerText);

break;

case "z":

pos.z = float.Parse(position.InnerText);

break;

}

}

}else if(prs.Name == "rotation")

{

foreach(XmlElement rotation in prs.ChildNodes)

{

switch(rotation.Name)

{

case "x":

rot.x = float.Parse(rotation.InnerText);

break;

case "y":

rot.y = float.Parse(rotation.InnerText);

break;

case "z":

rot.z = float.Parse(rotation.InnerText);

break;

}

}

}else if(prs.Name == "scale")

{

foreach(XmlElement scale in prs.ChildNodes)

{

switch(scale.Name)

{

case "x":

sca.x = float.Parse(scale.InnerText);

break;

case "y":

sca.y = float.Parse(scale.InnerText);

break;

case "z":

sca.z = float.Parse(scale.InnerText);

break;

}

}

}

}

 

//拿到 旋轉 縮放 平移 之後克隆新遊戲對象

GameObject ob = (GameObject)Instantiate(Resources.Load(asset),pos,Quaternion.Euler(rot));

ob.transform.localScale = sca;

 

}

}

}

}

}

 

// Update is called once per frame

void Update ()

{

 

}

 

void OnGUI()

{

if(GUI.Button(new Rect(0,0,200,200),"XML WORLD"))

{

Application.LoadLevel("JSONScene");

}

 

}

 

}

接着JSON場景中,建立一個空的遊戲對象,把JSON.cs掛上去。

C#

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

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

using UnityEngine;

using System.Collections;

using System.IO;

using LitJson;

 

public class JSON : MonoBehaviour {

 

// Use this for initialization

void Start ()

{

#if UNITY_EDITOR

  string filepath = Application.dataPath +"/StreamingAssets"+"/json.txt";

#elif UNITY_IPHONE

  string filepath = Application.dataPath +"/Raw"+"/json.txt";

#endif

 

StreamReader sr  = File.OpenText(filepath);

string  strLine = sr.ReadToEnd();

   JsonData jd = JsonMapper.ToObject(strLine);

   JsonData gameObjectArray = jd["GameObjects"];

int i,j,k;

for (i = 0; i < gameObjectArray.Count; i++)

{

   JsonData senseArray = gameObjectArray[i]["scenes"];

   for (j = 0; j < senseArray.Count; j++)

      {

string sceneName = (string)senseArray[j]["name"];

if(!sceneName.Equals("Assets/StarTrooper.unity"))

{

continue;

}

JsonData gameObjects = senseArray[j]["gameObject"];

 

for (k = 0; k < gameObjects.Count; k++)

{

string objectName = (string)gameObjects[k]["name"];

string asset = "Prefab/" + objectName;

Vector3 pos = Vector3.zero;

Vector3 rot = Vector3.zero;

Vector3 sca = Vector3.zero;

 

JsonData position = gameObjects[k]["position"];

JsonData rotation = gameObjects[k]["rotation"];

JsonData scale = gameObjects[k]["scale"];

 

pos.x = float.Parse((string)position[0]["x"]);

pos.y = float.Parse((string)position[0]["y"]);

pos.z = float.Parse((string)position[0]["z"]);

 

rot.x = float.Parse((string)rotation[0]["x"]);

rot.y = float.Parse((string)rotation[0]["y"]);

rot.z = float.Parse((string)rotation[0]["z"]);

 

sca.x = float.Parse((string)scale[0]["x"]);

sca.y = float.Parse((string)scale[0]["y"]);

sca.z = float.Parse((string)scale[0]["z"]);

 

GameObject ob = (GameObject)Instantiate(Resources.Load(asset),pos,Quaternion.Euler(rot));

ob.transform.localScale = sca;

 

}

 

   }

}

 

}

 

// Update is called once per frame

void Update () {

 

}

 

void OnGUI()

{

if(GUI.Button(new Rect(0,0,200,200),"JSON WORLD"))

{

Application.LoadLevel("XMLScene");

}

 

}

 

}

本例XML和JSON的解析與還原場景,在IOS真實設備上測試經過。

 

wKiom1RIrKmiZBTNAAJ12WmYfAg823.jpg

本例的下載地址:http://vdisk.weibo.com/s/k0_DE

雨鬆MOMO 祝你們學習愉快,準備睡覺,安 。歡迎討論與學習 嘿嘿。

相關文章
相關標籤/搜索