• (转)Unity 导出XML配置文件,动态加载场景


    参考:http://www.xuanyusong.com/archives/1919

    http://www.omuying.com/article/48.aspx
     
    主要功能:
    1.导出场景的配置文件
    2.导出当前场景中资源的AssetBundle
    3.客户端从服务器获取配置文件
    4.解析配置文件,并根据配置文件下载AssetBundle
    5.实例化并还原场景
     
    1.场景设置:将需要导出的场景资源设置为预设
     
    2.将场景配置导出为XML文件
     

    [code]csharpcode:

    using UnityEngine;
    using UnityEditor;
    using System.Collections;
    using System.Collections.Generic;
    using System.Xml;
    using System.IO;
    using System.Text;
    
    public class ExportSceneToXml : Editor 
    {
    	[MenuItem("Assets/Export Scene To XML From Selection")]
    	static void ExportXML()
    	{
    		string path = EditorUtility.SaveFilePanel ("Save Resource", "", "New Resource", "xml");
    		if (path.Length != 0) 
    		{
    			Object[] selectedAssetList = Selection.GetFiltered (typeof(Object), SelectionMode.DeepAssets);
    			
    			//遍历所有的游戏对象
    			foreach (Object selectObject in selectedAssetList) 
    			{
    				// 场景名称
    				string sceneName = selectObject.name;
    				// 场景路径
    				string scenePath = AssetDatabase.GetAssetPath(selectObject);
    				// 场景文件
    				//string xmlPath = path; //Application.dataPath + "/AssetBundles/Prefab/Scenes/" + sceneName + ".xml";
    				// 如果存在场景文件,删除
    				if(File.Exists(path)) File.Delete(path);
    				// 打开这个关卡
    				EditorApplication.OpenScene(scenePath);
    
    				XmlDocument xmlDocument = new XmlDocument();
    				// 创建XML属性
    				XmlDeclaration xmlDeclaration = xmlDocument.CreateXmlDeclaration("1.0", "utf-8", null);
    				xmlDocument.AppendChild(xmlDeclaration);
    				// 创建XML根标志
    				XmlElement rootXmlElement = xmlDocument.CreateElement("root");
    				// 创建场景标志
    				XmlElement sceneXmlElement = xmlDocument.CreateElement("scene");
    				sceneXmlElement.SetAttribute("sceneName", sceneName);
    				
    				foreach (GameObject sceneObject in Object.FindObjectsOfType(typeof(GameObject)))
    				{
    					// 如果对象是激活状态
    					if (sceneObject.transform.parent == null && sceneObject.activeSelf)
    					{
    						// 判断是否是预设
    						if(PrefabUtility.GetPrefabType(sceneObject) == PrefabType.PrefabInstance)
    						{
    							// 获取引用预设对象
    							Object prefabObject = EditorUtility.GetPrefabParent(sceneObject);
    							if(prefabObject != null)
    							{
    								XmlElement gameObjectXmlElement = xmlDocument.CreateElement("gameObject");
    								gameObjectXmlElement.SetAttribute("objectName", sceneObject.name);
    								gameObjectXmlElement.SetAttribute("objectAssetURL",  prefabObject.name);
    								
    								XmlElement transformXmlElement = xmlDocument.CreateElement("transform");
    								
    								// 位置信息
    								XmlElement positionXmlElement = xmlDocument.CreateElement("position");
    								positionXmlElement.SetAttribute("x", sceneObject.transform.position.x.ToString());
    								positionXmlElement.SetAttribute("y", sceneObject.transform.position.y.ToString());
    								positionXmlElement.SetAttribute("z", sceneObject.transform.position.z.ToString());
    								
    								// 旋转信息
    								XmlElement rotationXmlElement = xmlDocument.CreateElement("rotation");
    								rotationXmlElement.SetAttribute("x", sceneObject.transform.rotation.eulerAngles.x.ToString());
    								rotationXmlElement.SetAttribute("y", sceneObject.transform.rotation.eulerAngles.y.ToString());
    								rotationXmlElement.SetAttribute("z", sceneObject.transform.rotation.eulerAngles.z.ToString());
    								
    								// 缩放信息
    								XmlElement scaleXmlElement = xmlDocument.CreateElement("scale");
    								scaleXmlElement.SetAttribute("x", sceneObject.transform.localScale.x.ToString());
    								scaleXmlElement.SetAttribute("y", sceneObject.transform.localScale.y.ToString());
    								scaleXmlElement.SetAttribute("z", sceneObject.transform.localScale.z.ToString());
    								
    								transformXmlElement.AppendChild(positionXmlElement);
    								transformXmlElement.AppendChild(rotationXmlElement);
    								transformXmlElement.AppendChild(scaleXmlElement);    
    								
    								gameObjectXmlElement.AppendChild(transformXmlElement);
    								sceneXmlElement.AppendChild(gameObjectXmlElement);
    							}
    						}
    					}
    				}
    				rootXmlElement.AppendChild(sceneXmlElement);
    				xmlDocument.AppendChild(rootXmlElement);
    				// 保存场景数据
    				xmlDocument.Save(path);
    				// 刷新Project视图
    				AssetDatabase.Refresh();
    			}
    		}
    	}
    }
    

    导出结果参考:

    [code]xmlcode:

    <?xml version="1.0" encoding="utf-8"?>
    <root>
      <scene sceneName="DongTaiJiaZaiTest">
        <gameObject objectName="Box" objectAssetURL="Box">
          <transform>
            <position x="-1.293883" y="-0.07" z="1.41" />
            <rotation x="270" y="0" z="0" />
            <scale x="1" y="1" z="1" />
          </transform>
        </gameObject>
        <gameObject objectName="meinv" objectAssetURL="meinv">
          <transform>
            <position x="-1.75" y="1.36" z="11.28" />
            <rotation x="0" y="97.43578" z="0" />
            <scale x="1.09" y="1.09" z="1.09" />
          </transform>
        </gameObject>
        <gameObject objectName="Envirment" objectAssetURL="Envirment">
          <transform>
            <position x="0" y="0" z="0" />
            <rotation x="0" y="0" z="0" />
            <scale x="1" y="1" z="1" />
          </transform>
        </gameObject>
        <gameObject objectName="RigidBodyFPSController" objectAssetURL="RigidBodyFPSController">
          <transform>
            <position x="4.89" y="1.46" z="0.87" />
            <rotation x="0" y="253.2478" z="0" />
            <scale x="1" y="1" z="1" />
          </transform>
        </gameObject>
        <gameObject objectName="Sphere" objectAssetURL="Sphere">
          <transform>
            <position x="-2.63" y="3.28" z="-3.95" />
            <rotation x="270" y="0" z="0" />
            <scale x="1" y="1" z="1" />
          </transform>
        </gameObject>
      </scene>
    </root>

    3.将预设打包为AssetBundle,并上传到服务器
    打包Assetbundle编辑器脚本:

    [code]csharpcode:

    using UnityEngine;
    using System.Collections;
    using UnityEditor;
    
    public class Test : Editor
    {
    
        [MenuItem("Custom Editor/Create AssetBunldes Main For Android")]
        static void CreateAssetBunldesMainForAndroid()
        {
            //获取在Project视图中选择的所有游戏对象
            Object[] SelectedAsset = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets);
    
            //遍历所有的游戏对象
            foreach (Object obj in SelectedAsset)
            {
                //本地测试:建议最后将Assetbundle放在StreamingAssets文件夹下,如果没有就创建一个,因为移动平台下只能读取这个路径
                //StreamingAssets是只读路径,不能写入
                //服务器下载:就不需要放在这里,服务器上客户端用www类进行下载。
                string targetPath = Application.dataPath + "/StreamingAssets/" + obj.name + "Android" + ".assetbundle";
                if (BuildPipeline.BuildAssetBundle(obj, null, targetPath, BuildAssetBundleOptions.CollectDependencies, BuildTarget.Android))
                {
                    Debug.Log(obj.name + "资源打包成功");
                }
                else
                {
                    Debug.Log(obj.name + "资源打包失败");
                }
            }
            //刷新编辑器
            AssetDatabase.Refresh();
    
        }
        [MenuItem("Custom Editor/Create AssetBunldes Main For iPhone")]
        static void CreateAssetBunldesMainForiPhone()
        {
            //获取在Project视图中选择的所有游戏对象
            Object[] SelectedAsset = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets);
            //遍历所有的游戏对象
            foreach (Object obj in SelectedAsset)
            {
                string targetPath = Application.dataPath + "/StreamingAssets/" + obj.name + "iPhone" + ".assetbundle";
                if (BuildPipeline.BuildAssetBundle(obj, null, targetPath, BuildAssetBundleOptions.CollectDependencies, BuildTarget.iPhone))
                {
                    Debug.Log(obj.name + "资源打包成功");
                }
                else
                {
                    Debug.Log(obj.name + "资源打包失败");
                }
            }
            //刷新编辑器
            AssetDatabase.Refresh();
    
        }
    
        [MenuItem("Custom Editor/Create AssetBunldes ALL For Android")]
        static void CreateAssetBunldesALLForAndroid()
        {
    
            Caching.CleanCache();
            string Path = Application.dataPath + "/StreamingAssets/ALLAndroid.assetbundle";
            Object[] SelectedAsset = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets);
            foreach (Object obj in SelectedAsset)
            {
                Debug.Log("Create AssetBunldes name :" + obj);
            }
    
            //这里注意第二个参数就行
            if (BuildPipeline.BuildAssetBundle(null, SelectedAsset, Path, BuildAssetBundleOptions.CollectDependencies, BuildTarget.Android))
            {
                AssetDatabase.Refresh();
            }
            else
            {
    
            }
        }
        [MenuItem("Custom Editor/Create AssetBunldes ALL For iPhone")]
        static void CreateAssetBunldesALLForiPhone()
        {
    
            Caching.CleanCache();
    
    
            string Path = Application.dataPath + "/StreamingAssets/ALLiPhone.assetbundle";
    
    
            Object[] SelectedAsset = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets);
    
            foreach (Object obj in SelectedAsset)
            {
                Debug.Log("Create AssetBunldes name :" + obj);
            }
    
            //这里注意第二个参数就行
            if (BuildPipeline.BuildAssetBundle(null, SelectedAsset, Path, BuildAssetBundleOptions.CollectDependencies, BuildTarget.iPhone))
            {
                AssetDatabase.Refresh();
            }
            else
            {
    
            }
        }
        [MenuItem("Custom Editor/Create Scene For Android")]
        static void CreateSceneALLForAndroid()
        {
            Caching.CleanCache();
            Object[] SelectedAsset = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets);
            foreach (Object obj in SelectedAsset)
            {
                string Path = Application.dataPath + "/StreamingAssets/" + obj.name + "Android" + ".unity3d";
                string[] levels = { @"Assets/Scenes/ExportedScene/" + obj.name + ".unity" };
                BuildPipeline.BuildPlayer(levels, Path, BuildTarget.Android, BuildOptions.BuildAdditionalStreamedScenes);
                Debug.Log("Craete Scene" + Path + "Complete!!");
            }
            AssetDatabase.Refresh();
        }
    
        [MenuItem("Custom Editor/Create Scene For iPhone")]
        static void CreateSceneALLForiPhone()
        {
            Caching.CleanCache();
            Object[] SelectedAsset = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets);
            foreach (Object obj in SelectedAsset)
            {
                string Path = Application.dataPath + "/StreamingAssets/" + obj.name + "iPhone" + ".unity3d";
                string[] levels = { @"Assets/Scenes/ExportedScene/" + obj.name + ".unity" };
                BuildPipeline.BuildPlayer(levels, Path, BuildTarget.iPhone, BuildOptions.BuildAdditionalStreamedScenes);
                Debug.Log("Craete Scene" + Path + "Complete!!");
            }
            AssetDatabase.Refresh();
        }
    
    }
    
     
    4.将服务器的路径修改到XML配置文件中,并将XML上传到服务器
     
    5.在Unity客户端下载XML并解析,下载并实例化对应的资源

    [code]csharpcode:

    using UnityEngine;
    using System.Collections;
    using System.IO;
    using System.Collections.Generic;
    using System.Xml;
    
    public class GetXMLDoc : MonoBehaviour
    {
    
    	string filePath;
    	public string XMLDocURL = "http://************.xml";
    
    	void Awake ()
    	{
    		filePath = Application.persistentDataPath + "/XMLDoc1028.xml";
    		if (File.Exists (filePath)) {
    			File.Delete (filePath);
    		}
    		WWW www = new WWW (XMLDocURL);
    		StartCoroutine (DownloadXMLDoc (www));
    
    	}
    
    	IEnumerator DownloadXMLDoc (WWW www)
    	{
    		yield return www;
    		if (www.isDone) {
    			Debug.Log ("WWW is done");
    			byte[] bts = www.bytes;
    			int length = bts.Length;
    			CreateXMLDoc (filePath, bts, length);
    		}
    
    	}
    
    	void CreateXMLDoc (string path, byte[] info, int lenth)
    	{
    		Debug.Log ("Start to create XML");
    		Stream sw;
    		FileInfo t = new FileInfo (path);
    		if (!t.Exists) {
    			sw = t.Create ();
    
    		} else {
    			return;
    		}
    		sw.Write (info, 0, lenth);
    		sw.Close ();
    		sw.Dispose ();
    		Debug.Log ("XML create sucess");
    		LoadScene ();
    //        下载完毕之后可以读取并进行实例化了
    	}
    
    	void LoadScene ()
    	{
    		Debug.Log ("开始加载");
    		if (File.Exists (filePath)) {
    			XmlDocument xmlDoc = new XmlDocument ();
    			xmlDoc.Load (filePath);
    			XmlNodeList nodeList = xmlDoc.SelectSingleNode ("root").ChildNodes;
    			foreach (XmlElement scene  in nodeList) {
    				//因为我的XML是把所有游戏对象全部导出, 所以这里判断一下只解析需要的场景中的游戏对象
    				//JSON和它的原理类似
    //                if (!scene.GetAttribute("name").Equals("Assets/StarTrooper.unity"))
    //                {
    //                    continue;
    //                }
     
    				foreach (XmlElement gameObjects in scene.ChildNodes) {
    //                    取得资源地址
    					string assetRUL = gameObjects.GetAttribute ("objectAssetURL");
    					string assetName = gameObjects.GetAttribute ("objectName");
    					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") {
    
    								pos.x = float.Parse(prs.GetAttribute("x"));
    								pos.y = float.Parse(prs.GetAttribute("y"));
    								pos.z = float.Parse(prs.GetAttribute("z"));
    
    //								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") {
    
    								rot.x = float.Parse (prs.GetAttribute("x"));
    								rot.y = float.Parse(prs.GetAttribute("y"));
    								rot.z = float.Parse(prs.GetAttribute("z"));
    
    //								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") {
    								sca.x = float.Parse (prs.GetAttribute("x"));
    								sca.y = float.Parse(prs.GetAttribute("y"));
    								sca.z = float.Parse(prs.GetAttribute("z"));
    
    //								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;
    //									}
    //								}
    							}
    						}
    						Debug.Log ("准备下载:" + assetRUL);
    //                        开始下载并实例化对象
    						Debug.Log (assetName + ":pos=" + pos);
    						Debug.Log (assetName + ":rot=" + pos);
    						Debug.Log (assetName + ":sca=" + pos);
    						StartCoroutine (DownloadAsset (new WWW (assetRUL), pos, rot, sca));
    
    
    
    						//拿到 旋转 缩放 平移 以后克隆新游戏对象
    //                        GameObject ob = (GameObject)Instantiate(Resources.Load(asset), pos, Quaternion.Euler(rot));
    //                        ob.transform.localScale = sca;
     
                        
    					}
    				}
    
    			}
    
    		}
    
    	}
    
    
    
    	IEnumerator DownloadAsset (WWW www, Vector3 pos, Vector3 rot, Vector3 sca)
    	{
    
    		yield return www;
    		if (www.isDone) {
    //            yield return Instantiate(www.assetBundle.mainAsset,pos,pos,Quaternion.Euler(rot));
    			GameObject ob = (GameObject)Instantiate (www.assetBundle.mainAsset, pos, Quaternion.Euler (rot));
    			ob.transform.localScale = sca;
    			www.assetBundle.Unload (false);
    		}
    	}
    
    }
  • 相关阅读:
    map按照值排序
    结构体的三种排序方式
    归并排序
    数组模拟双向链表
    二刷斐波那契高精度
    2019年9月训练(贰)区间DP (luogu 4290)
    2019年9月训练(壹)数位DP (HDU 2089)
    2019年8月训练(贰)
    2019年8月训练(壹)二分,三分
    2019年7月训练(柒)
  • 原文地址:https://www.cnblogs.com/backlighting/p/5061527.html
Copyright © 2020-2023  润新知