Unity场景导出XML并加载场景
发表于2018-10-17
为了尽可能加快从网络加载场景,我们通常可以把场景先导出成 XML,在使用时候在根据xml的配置进行加载完成场景的构建。把现有的场景导出xml需要使用到Unity的编辑类需要引入命名空间,unityEditor,直接把导出xml做成一个工具。
具体代码如下:
using UnityEngine; using System.Collections; using UnityEditor; using System.Collections.Generic; using System.Xml; using System.IO; using System.Text; using LitJson; using UnityEngine.SceneManagement; public class MyEditor : Editor { //将所有游戏场景导出为XML格式 [MenuItem ("GameObject/ExportXML")] static void ExportXML () { string LevelName = SceneManager.GetActiveScene().name; if (LevelName == "") Debug.LogError("请保存你的场景"); string filepath = Application.dataPath + @"/StreamingAssets/"+LevelName+".xml"; //string filepath = Application.dataPath + @"/StreamingAssets/lv01.xml"; if (!File.Exists (filepath)) { File.Delete(filepath); } XmlDocument xmlDoc = new XmlDocument(); XmlElement root = xmlDoc.CreateElement("gameObjects"); Debug.Log(UnityEditor.EditorBuildSettings.scenes[0]); //遍历所有的游戏场景 foreach (UnityEditor.EditorBuildSettingsScene S in UnityEditor.EditorBuildSettings.scenes) { Debug.Log("123"); //当关卡启用 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(); Debug.LogError("场景保存完成!!"); } }
这里需要注意,代码会根据你场景的名字进行打包,需要注意的是需要把场景添加到
下面就是加载代码:
using UnityEngine; using System.Collections; using System.Xml; using System.IO; public class XML : MonoBehaviour { // Use this for initialization public string LeveName = "my"; public string FileName = ""; void Start () { //电脑和iphong上的路径是不一样的,这里用标签判断一下。 #if UNITY_EDITOR string filepath = Application.dataPath +"/StreamingAssets"+"/"+LeveName+".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"); if (FileName == "") return; string asset = FileName + "/" + 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; } } } } } }
这样就可以了,实现场景导出xml,在利用代码进行加载整个场景。
来自:https://blog.csdn.net/liang_704959721/article/details/78215901