unity3d场景导出XML或JSON并且解析还原场景

导出 unity 场景的所有游戏对象信息,一种是XML一种是JSON。本篇文章我们把游戏场景中游戏对象的、旋转、缩放、平移与Prefab的名称导出在XML与JSON中。然后解析刚刚导出的XML或JSON通过脚本把导出的游戏场景还原。在Unity官网上下载随便下载一个demo Project,如下图所示这是我刚刚在官网上下载的一个范例程序。
接着将层次视图中的所有游戏对象都封装成Prefab保存在资源路径中,这里注意一下如果你的Prefab绑定的脚本中有public Object 的话 ,需要在代码中改一下。。用 Find() FindTag()这类方法在脚本中Awake()方法中来拿,不然Prefab动态加载的时候无法赋值的,如下图所示,我把封装的Prefab对象都放在了Resources/Prefab文件夹下。
OK,现在我们就需要编写我们的导出工具、在Project视图中创建Editor文件夹,接着创建脚本MyEditor 。如下图所示。
因为编辑的游戏场景数量比较多,导出的时候我们需要遍历所有的游戏场景,一个一个的读取场景信息。然后取得游戏场景中所有游戏对象的Prefab的 名称 旋转 缩放 平移。有关XML的使用请大家看我的上一篇文章:Unity3D研究院之使用 C#合成解析XML与JSON(四十一)代码中我只注释重点的部分,嘿嘿。
MyEditor.cs

usingUnityEngine;
002
usingSystem.Collections;

003 usingUnityEditor;
004 usingSystem.Collections.Generic;
005 usingSystem.Xml;
006 usingSystem.IO;
007 usingSystem.Text;
008 usingLitJson;
009 publicclassMyEditor : Editor
010 {
011 //将所有游戏场景导出为XML格式
012 [MenuItem ("GameObject/ExportXML")]
013 staticvoidExportXML ()
014 {
015 stringfilepath = Application.dataPath + @"/StreamingAssets/my.xml";
016 if(!File.Exists (filepath))
017 018 File.Delete(filepath);
019 }
020 XmlDocument xmlDoc = newXmlDocument();
021 XmlElement root = xmlDoc.CreateElement("gameObjects");
022 //遍历所有的游戏场景
023 foreach(UnityEditor.EditorBuildSettingsScene S inUnityEditor.EditorBuildSettings.scenes)
024 025 //当关卡启用
026 if(S.enabled)
027 {
028 //得到关卡的名称
029 stringname = S.path;
030 //打开这个关卡
031 EditorApplication.OpenScene(name);
032 XmlElement scenes = xmlDoc.CreateElement("scenes");
033 scenes.SetAttribute("name",name);
034 foreach(GameObject obj inObject.FindObjectsOfType(typeof(GameObject)))
035 {
036 if(obj.transform.parent == null)
037 038 XmlElement gameObject = xmlDoc.CreateElement("gameObjects");
039 gameObject.SetAttribute("name",obj.name);
040
041 gameObject.SetAttribute("asset",obj.name + ".prefab");
042 XmlElement transform = xmlDoc.CreateElement("transform");
043 XmlElement position = xmlDoc.CreateElement("position");
044 XmlElement position_x = xmlDoc.CreateElement("x");
045 position_x.InnerText = obj.transform.position.x+"";
046 XmlElement position_y = xmlDoc.CreateElement("y");
047 position_y.InnerText = obj.transform.position.y+"";
048 XmlElement position_z = xmlDoc.CreateElement("z");
049 position_z.InnerText = obj.transform.position.z+"";
050 position.AppendChild(position_x);
051 position.AppendChild(position_y);
052 position.AppendChild(position_z);
053 054 XmlElement rotation = xmlDoc.CreateElement("rotation");
055 XmlElement rotation_x = xmlDoc.CreateElement("x");
056 rotation_x.InnerText = obj.transform.rotation.eulerAngles.x+"";
057 XmlElement rotation_y = xmlDoc.CreateElement("y");
058 rotation_y.InnerText = obj.transform.rotation.eulerAngles.y+"";
059 XmlElement rotation_z = xmlDoc.CreateElement("z");
060 rotation_z.InnerText = obj.transform.rotation.eulerAngles.z+"";
061 rotation.AppendChild(rotation_x);
062 rotation.AppendChild(rotation_y);
063 rotation.AppendChild(rotation_z);
064 065 XmlElement scale = xmlDoc.CreateElement("scale");
066 XmlElement scale_x = xmlDoc.CreateElement("x");
067 scale_x.InnerText = obj.transform.localScale.x+"";
068 XmlElement scale_y = xmlDoc.CreateElement("y");
069 scale_y.InnerText = obj.transform.localScale.y+"";
070 XmlElement scale_z = xmlDoc.CreateElement("z");
071 scale_z.InnerText = obj.transform.localScale.z+"";
072 073 scale.AppendChild(scale_x);
074 scale.AppendChild(scale_y);
075 scale.AppendChild(scale_z);
076 077 transform.AppendChild(position);
078 transform.AppendChild(rotation);
079 transform.AppendChild(scale);
080 081 gameObject.AppendChild(transform);
082 scenes.AppendChild(gameObject);
083 root.AppendChild(scenes);
084 xmlDoc.AppendChild(root);
085 xmlDoc.Save(filepath);
086 087 }
088 089 }
090 091 //刷新Project视图, 不然需要手动刷新哦
092 AssetDatabase.Refresh();
093 094 095 //将所有游戏场景导出为JSON格式
096 [MenuItem ("GameObject/ExportJSON")]
097 staticvoidExportJSON ()
098 099 stringfilepath = Application.dataPath + @"/StreamingAssets/json.txt";
100 FileInfo t = newFileInfo(filepath);
101 102 103 104 105 StreamWriter sw = t.CreateText();
106 107 StringBuilder sb = newStringBuilder ();
108 JsonWriter writer = newJsonWriter (sb);
109 writer.WriteObjectStart ();
110 writer.WritePropertyName ("GameObjects");
111 writer.WriteArrayStart ();
112 113 114 115 116 117 118 119 writer.WriteObjectStart();
120 writer.WritePropertyName("scenes");
121 writer.WriteArrayStart ();
122 123 writer.WritePropertyName("name");
124 writer.Write(name);
125 writer.WritePropertyName("gameObject");
126 127 128 129 130 131 132 writer.WriteObjectStart();
133 writer.WritePropertyName("name");
134 writer.Write(obj.name);
135 136 writer.WritePropertyName("position");
137 writer.WriteArrayStart ();
138 139 writer.WritePropertyName("x");
140 writer.Write(obj.transform.position.x.ToString("F5"));
141 writer.WritePropertyName("y");
142 writer.Write(obj.transform.position.y.ToString("F5"));
143 writer.WritePropertyName("z");
144 writer.Write(obj.transform.position.z.ToString("F5"));
145 writer.WriteObjectEnd();
146 writer.WriteArrayEnd();
147 148 writer.WritePropertyName("rotation");
149 150 151 152 writer.Write(obj.transform.rotation.eulerAngles.x.ToString("F5"));
153 154 writer.Write(obj.transform.rotation.eulerAngles.y.ToString("F5"));
155 156 writer.Write(obj.transform.rotation.eulerAngles.z.ToString("F5"));
157 158 159 160 writer.WritePropertyName("scale");
161 162 163 164 writer.Write(obj.transform.localScale.x.ToString("F5"));
165 166 writer.Write(obj.transform.localScale.y.ToString("F5"));
167 168 writer.Write(obj.transform.localScale.z.ToString("F5"));
169 170 171 172 173 174 175 176 writer.WriteArrayEnd();
177 writer.WriteObjectEnd();
178 179 180 181 182 writer.WriteArrayEnd();
183 writer.WriteObjectEnd ();
184 185 sw.WriteLine(sb.ToString());
186 sw.Close();
187 sw.Dispose();
188 AssetDatabase.Refresh();
189 190 }
OK。此时我们就可以导出游戏场景的信息拉,注意游戏场景的需要现在Project Setting 中注册。点击 GameObject – > Export XML 和 GameObject – > ExportJson 菜单项即可开始生成。
如下图所示,场景导出完毕后,会将xml 与Json 文件保存在StreamingAssets路径下,放在这里的原因是方便移动平台移植,因为它们属于二进制文件,移动平台在读取二进制文件的路径是不一样的。一定要放在这里喔。
接着,我继续创建两个游戏场景,一个用来解析XML的场景,一个用来解析JSON的场景。
XML场景中,创建一个空的游戏对象,把XML.cs挂上去。
publicclassXML : MonoBehaviour {
// Use this for initialization
voidStart ()
//电脑和iphong上的路径是不一样的,这里用标签判断一下。
#if UNITY_EDITOR
stringfilepath = Application.dataPath +"/StreamingAssets"+"/my.xml";
#elif UNITY_IPHONE
stringfilepath = Application.dataPath +"/Raw"+"/my.xml";
#endif
//如果文件存在话开始解析。
if(File.Exists (filepath))
XmlDocument xmlDoc = newXmlDocument();
xmlDoc.Load(filepath);
XmlNodeList nodeList=xmlDoc.SelectSingleNode("gameObjects").ChildNodes;
foreach(XmlElement sceneinnodeList)
//因为我的XML是把所有游戏对象全部导出, 所以这里判断一下只解析需要的场景中的游戏对象
//JSON和它的原理类似
if(!scene.GetAttribute("name").Equals("Assets/StarTrooper.unity"))
continue;
foreach(XmlElement gameObjects inscene.ChildNodes)
stringasset = "Prefab/"+ gameObjects.GetAttribute("name");
Vector3 pos = Vector3.zero;
Vector3 rot = Vector3.zero;
Vector3 sca = Vector3.zero;
foreach(XmlElement transform ingameObjects.ChildNodes)
foreach(XmlElement prs intransform.ChildNodes)
{
if(prs.Name == "position")
{
foreach(XmlElement position inprs.ChildNodes)
switch(position.Name)
{
case"x":
pos.x = float.Parse(position.InnerText);
break;
case"y":
pos.y = float.Parse(position.InnerText);
case"z":
pos.z = float.Parse(position.InnerText);
}
}elseif(prs.Name == "rotation")
foreach(XmlElement rotation inprs.ChildNodes)
switch(rotation.Name)
case"x":
rot.x = float.Parse(rotation.InnerText);
break;
case"y":
rot.y = float.Parse(rotation.InnerText);
case"z":
rot.z = float.Parse(rotation.InnerText);
}elseif(prs.Name == "scale")
foreach(XmlElement scale inprs.ChildNodes)
switch(scale.Name)
sca.x = float.Parse(scale.InnerText);
sca.y = float.Parse(scale.InnerText);
sca.z = float.Parse(scale.InnerText);
}
//拿到 旋转 缩放 平移 以后克隆新游戏对象
GameObject ob = (GameObject)Instantiate(Resources.Load(asset),pos,Quaternion.Euler(rot));
ob.transform.localScale = sca;
// Update is called once per frame
voidUpdate ()
voidOnGUI()
if(GUI.Button(newRect(0,200,200),"XML WORLD"))
Application.LoadLevel("JSONScene");
接着JSON场景中,创建一个空的游戏对象,把JSON.cs挂上去。
02 03 04 05 06 publicclassJSON : MonoBehaviour {
07 08 09 10 11 12 stringfilepath = Application.dataPath +"/StreamingAssets"+"/json.txt";
13 14 stringfilepath = Application.dataPath +"/Raw"+"/json.txt";
15 #endif
16 17 StreamReader sr= File.OpenText(filepath);
18 stringstrLine = sr.ReadToEnd();
19 JsonData jd = JsonMapper.ToObject(strLine);
20 JsonData gameObjectArray = jd["GameObjects"];
21 inti,j,k;
22 for(i = 0; i < gameObjectArray.Count; i++)
23 24 JsonData senseArray = gameObjectArray["scenes"];
25 for(j = 0; j < senseArray.Count; j++)
26 {
27 stringsceneName = (string)senseArray[j]["name"];
28 if(!sceneName.Equals("Assets/StarTrooper.unity"))
29 30 31 32 JsonData gameObjects = senseArray[j]["gameObject"];
33 34 for(k = 0; k < gameObjects.Count; k++)
35 36 stringobjectName = (string)gameObjects[k]["name"];
37 stringasset = "Prefab/"+ objectName;
38 39 40 41 42 JsonData position = gameObjects[k]["position"];
43 JsonData rotation = gameObjects[k]["rotation"];
44 JsonData scale = gameObjects[k]["scale"];
45 46 pos.x = float.Parse((string)position[0]["x"]);
47 pos.y = float.Parse((string)position[0]["y"]);
48 pos.z = float.Parse((string)position[0]["z"]);
49 50 rot.x = float.Parse((string)rotation[0]["x"]);
51 rot.y = float.Parse((string)rotation[0]["y"]);
52 rot.z = float.Parse((string)rotation[0]["z"]);
53 54 sca.x = float.Parse((string)scale[0]["x"]);
55 sca.y = float.Parse((string)scale[0]["y"]);
56 sca.z = float.Parse((string)scale[0]["z"]);
57 58 59 60 61 62 63 }
64 65 66 67 68 69 voidUpdate () {
70 71 72 73 74 75
76 77 Application.LoadLevel("XMLScene");
78 79 80 81 82 本例XML和JSON的解析与还原场景,在IOS真实设备上测试通过。
本例的下载地址:http://vdisk.weibo.com/s/k0_DE

相关文章

这篇文章将为大家详细讲解有关Unity3D中如何通过Animator动画...
这篇文章主要介绍了Unity3D如何播放游戏视频,具有一定借鉴价...
这篇文章给大家分享的是有关Unity3D各平台路径是什么的内容。...
小编给大家分享一下Unity3D如何实现移动平台上的角色阴影,希...
如何解析基于Unity3D的平坦四叉树地形与Virtual Texture的分...
这篇文章主要介绍Unity3D如何实现动态分辨率降低渲染开销,文...