http://www.xuanyusong.com/archives/1919node
導出Unity場景的全部遊戲對象信息,一種是XML一種是JSON。本篇文章咱們把遊戲場景中游戲對象的、旋轉、縮放、平移與Prefab的名稱導出在XML與JSON中。而後解析剛剛導出的XML或JSON經過腳本把導出的遊戲場景還原。在Unity官網上下載隨便下載一個demo Project,以下圖所示這是我剛剛在官網上下載的一個範例程序。json
接着將層次視圖中的全部遊戲對象都封裝成Prefab保存在資源路徑中,這裏注意一下若是你的Prefab綁定的腳本中有public Object 的話 ,須要在代碼中改一下。。用 Find() FindTag()這類方法在腳本中Awake()方法中來拿,否則Prefab動態加載的時候沒法賦值的,以下圖所示,我把封裝的Prefab對象都放在了Resources/Prefab文件夾下。app
OK,如今咱們就須要編寫咱們的導出工具、在Project視圖中建立Editor文件夾,接着建立腳本MyEditor 。以下圖所示。ide
由於編輯的遊戲場景數量比較多,導出的時候咱們須要遍歷全部的遊戲場景,一個一個的讀取場景信息。而後取得遊戲場景中全部遊戲對象的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 菜單項便可開始生成。
以下圖所示,場景導出完畢後,會將xml 與Json 文件保存在StreamingAssets路徑下,放在這裏的緣由是方便移動平臺移植,由於它們屬於二進制文件,移動平臺在讀取二進制文件的路徑是不同的。必定要放在這裏喔。
接着,我繼續建立兩個遊戲場景,一個用來解析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真實設備上測試經過。
本例的下載地址:http://vdisk.weibo.com/s/k0_DE
雨鬆MOMO 祝你們學習愉快,準備睡覺,安 。歡迎討論與學習 嘿嘿。