Unity3d Research Institute Export the scene XML or JSON or binary and parse the restore scene

Source: Internet
Author: User
Tags sca

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

Export all game object information from unity scene, one is XML, one is JSON. In this article, we export the name of the game object, rotate, zoom, translate and prefab in the game scene in XML and JSON. Then parse the XML that you just exported or JSON to restore the exported game scene through a script. Download a demo Project on the Unity official website, as shown in this is an example program I just downloaded on the official website.

Then all the game objects in the hierarchy view are encapsulated into prefab saved in the resource path, note that if you have a public Object in your prefab-bound script, you need to change it in the code: Use the Find () Findtag () method in the script awake () method to take, or prefab dynamic loading can not be assigned to the value, as shown, I put the encapsulated prefab objects in the Resources/prefab folder.

OK, now we need to write our export tool, create the Editor folder in Project view, and then create the script Myeditor. As shown in.

Because of the number of editing game scenes, when exporting we need to traverse all the game scenes, one by one to read the scene information. Then get the prefab name of all game objects in the game scene rotate Zoom pan. About the use of XML please look at my previous article: Unity3d Research Institute of the use of C # Synthesis parsing XML and JSON (41) Code I only note the focus of the part, hey.

MyEditor.cs[Code]:
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{//export all game scenes to XML format [MenuItem ("Gameobject /exportxml ")]static void ExportXML () {string filepath = Application.datapath + @"/streamingassets/my.xml "; File.exists (filepath)) {file.delete (filepath);} XmlDocument xmldoc = new XmlDocument (); XmlElement root = Xmldoc.createelement ("gameobjects");//traverse all game scenes foreach (Unityeditor.editorbuildsettingsscene S in UnityEditor.EditorBuildSettings.scenes) {//When the level is enabled if (s.enabled) {//Get the name of the level                Called String name = S.path; Open this level 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); }}}}//Refresh Project view, otherwise you need to manually refresh Oh Assetdatabase.refresh ();} Export all game scenes to JSON format [MenuItem ("GameobJect/exportjson ")]static void Exportjson () {string filepath = Application.datapath + @"/streamingassets/json.txt "; FileInfo t = new FileInfo (filepath);        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. At this point we can export the game scene information pull, note that the game scene needs to be registered in Project Setting now. Click the gameobject–> Export XML and gameobject–> exportjson menu item to start the build.

As shown, after the scene has been exported, the XML and JSON files are saved in the Streamingassets path, and the reason for this is that it is easy to migrate the mobile platform because they belong to binary files and the mobile platform is not the same as the path to the binary files. Be sure to put it here.

Next, I continued to create two game scenes, a scene to parse the XML, and a scene to parse the JSON.

XML scene, create an empty game object and hang the XML.cs.

[Code]:
Using unityengine;using system.collections;using system.xml;using System.io;public class Xml:monobehaviour {//Use this For Initializationvoid Start () {//the path on the computer and Iphong is not the same, here is a label to judge. #if unity_editorstring filepath = application.datapath + "/streamingassets" + "/my.xml"; #elif unity_iphone string filepath = Application.datapath + "/raw" + "/my.xml"; #endif//If the file exists, start parsing. if (file.exists (filepath)) {XmlDocument xmldoc = new XmlDocument (); Xmldoc.load (filepath); XmlNodeList Nodelist=xmldoc.selectsinglenode ("Gameobjects"). Childnodes;foreach (XmlElement scene in nodeList) {//Because my XML is to export all the game objects, so here's to judge only the game objects in the scene that need to be parsed//json and it works like 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":p os.x = float. Parse (position. InnerText); Break;case "Y":p os.y = float. Parse (position. InnerText); Break;case "Z":p os.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;}}} Get the rotation zoom pan after cloning new game object Gameobject ob = (gameobject) instantiate (Resources.load (asset), Pos,quaternion.euler (Rot)); O B.transform.localscale = SCA;}}}} Update is called once per framevoid update () {}void Ongui () {if (GUI. button (new Rect (0,0,200,200), "XML World")) {Application.loadlevel ("Jsonscene");}}}
then, in the JSON scene, create an empty game object and hang up the JSON.cs.

[Code]:
Using unityengine;using system.collections;using system.io;using Litjson;public class Json:monobehaviour {//Use this fo R initializationvoid Start () {#if unity_editor string filepath = Application.datapath + "/streamingassets" + "/json.txt"; # Elif Unity_iphone String filepath = Application.datapath + "/raw" + "/json.txt"; #endifStreamReader sr = File.OpenText (File path); 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 senseAr   Ray = gameobjectarray[i]["scenes"]; for (j = 0; J < Sensearray.count; J + +) {string scenename = (string) sensearray[j]["name"];if (!scenename.equals ("the Ets/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"];p os.x = float. Parse ((String) position[0]["x"]);p os.y = float. Parse ((String) position[0]["Y"]);p os.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 framevoid update () {}void Ongui () {if (GUI. button (new Rect (0,0,200,200), "JSON World") {Application.loadlevel ("Xmlscene");}}}

This example parses and restores the XML and JSON scenarios and tests the pass on the iOS real device.

In this case: Http://vdisk.weibo.com/s/k0_DE

The rain pine Momo wishes everybody to study happily, prepares to sleep, Ann. Welcome to discuss and learn hehe.

Add

With the recent interaction between the client and server, using JSON and XML will feel that the amount of data is too large to affect efficiency. Finally, the binary method is used to complete the process. As shown, using binary can save space to 803K, is not very good? Let's start learning how to make it.

Increase the export binaries option when exporting a scene, as shown in the code below.

[Code]:
[MenuItem ("gameobject/binary")]static void Xmljsontobinary () {string filepath = Application.datapath + @ "/ Streamingassets/binary.txt "; if (file.exists (filepath)) {file.delete (filepath);} FileStream  fs = new FileStream (filepath, filemode.create); BinaryWriter bw = new BinaryWriter (fs); foreach (Unityeditor.editorbuildsettingsscene S in UnityEditor.EditorBuildSettings.scenes)        {            if (s.enabled)            {string name = S.path; Editorapplication.openscene (name); foreach (Gameobject obj in Object.findobjectsoftype (typeof (Gameobject))) {    if (obj.transform.parent = = null)    {//annotations are written directly to the string bw. Write (name); bw. Write (obj.name); short posx = (short) (obj.transform.position.x * 100);

Annotations

The core class used when writing binary data is BinaryWriter, binary is binary meaning, visible operation binary write is used BinaryWriter. The commonly used data type allocates a fixed number of bytes, assuming that BinaryWriter writes a short then takes up 2 bytes, writes an int that takes up 4 bytes, and if it is an array, the array type byte length is multiplied by the array length.

byte: One byte (8 bits)
Short : Two bytes (16 bits)
int: Four bytes (32 bits) (one word length)
Long: Eight bytes (64 bits)
float: Four bytes (32 bits)
Double: eight bytes (64 bits)

and then talking about string, it's not a standard data type, it's an object, and its byte length is mutable. At first I also struggled with the string for a little while. Also , BinaryWriter writes the length of the string as a byte, and then stores the string's byte length. Then parse the string, you need to parse the length of the string, and then take the length of the corresponding length of the byte array, and then convert the byte array into a string on the line. Also, I used the short x 100 above in order to save the length, because short is 2 bytes, and float is 4 bytes. I was able to convert it to float by dividing it by 100 when I was parsing.

Then we look at the parsed code, and when we write it we use the BinaryWriter so it should be binaryreader.

Binary.cs

[Code]:
Using unityengine;using system.collections;using system.io;using system.text;using system;public class Binary: monobehaviour {void Start () {string filepath = Application.datapath + @ "/streamingassets/binary.txt"; if (File.exists ( FilePath)) {FileStream fs = new FileStream (Filepath,filemode.open);    BinaryReader br = new BinaryReader (fs); int index = 0; The binary byte stream is read all in this byte array the parameter passed by//readbytes is a length, that is, the length of the stream byte[] Tempall = br. Readbytes ((int) fs. length);//Start parsing this byte array while (TRUE) {//when exceeding the stream length, jump out of the loop if (index >= tempall. Length) {break;} Gets the first byte that is the length of the string int scenelength = tempall[index];byte []scenename = new byte [Scenelength];index + = 1;//copies the corresponding length according to length The byte array of degrees System.Array.Copy (tempall,index,scenename,0,scenename.length);//Then converts the byte array corresponding to string sname =    System.Text.Encoding.Default.GetString (Scenename); Here is the same principle as above, not to repeat int objectlength = tempall[index + scenename.length];byte []objectname = new byte [Objectlength];index + = s Cenename.length + 1; System.Array.Copy (tempall,index,objectname,0,objectnAme.    length); string oname = System.Text.Encoding.Default.GetString (objectName);//The following is to take the short of each short is 2 bytes. Index + = objectname.length;byte[] Posx = new byte[2]; System.Array.Copy (TEMPALL,INDEX,POSX,0,POSX. Length), or//get the corresponding value and divide by 100 is the float pull.    float x = System.BitConverter.ToInt16 (posx,0)/100.0f; Below are almost the index + = posx. length;byte[] Posy = new byte[2]; System.Array.Copy (Tempall,index,posy,0,posy. Length), Float y = System.BitConverter.ToInt16 (posy,0)/100.0f;index + = Posy. length;byte[] Posz = new byte[2]; System.Array.Copy (Tempall,index,posz,0,posz. Length), float z = System.BitConverter.ToInt16 (posz,0)/100.0f;index + = Posz. length;byte[] Rotx = new byte[2]; System.Array.Copy (Tempall,index,rotx,0,rotx. Length), Float rx = System.BitConverter.ToInt16 (rotx,0)/100.0f;index + = Rotx. length;byte[] Roty = new byte[2]; System.Array.Copy (Tempall,index,roty,0,roty. Length) Float ry = System.BitConverter.ToInt16 (roty,0)/100.0f;index + = Roty. length;byte[] Rotz = new byte[2]; System.Array.Copy (TempaLl,index,rotz,0,rotz. float RZ = System.BitConverter.ToInt16 (rotz,0)/100.0f;index + = Rotz. length;byte[] Scax = new byte[2]; System.Array.Copy (Tempall,index,scax,0,scax. Length), Float SX = System.BitConverter.ToInt16 (scax,0)/100.0f;index + = Scax. length;byte[] Scay = new byte[2]; System.Array.Copy (Tempall,index,scay,0,scay. Length); Float sy = System.BitConverter.ToInt16 (scay,0)/100.0f;index + = Scay. length;byte[] Scaz = new byte[2]; System.Array.Copy (Tempall,index,scaz,0,scaz. Length); float sz = System.BitConverter.ToInt16 (scaz,0)/100.0f;index+=scaz. Length;if (sname. Equals ("assets/startrooper.unity") {///Last here to generate the scene out of string asset = "prefab/" + oname; Vector3 pos = new Vector3 (x, y, z); Vector3 rot = new Vector3 (RX,RY,RZ); Vector3 SCA = new Vector3 (SX,SY,SZ); Gameobject ob = (gameobject) instantiate (Resources.load (asset), Pos,quaternion.euler (Rot)); Ob.transform.localScale = SCA;}}}} Update is called once per framevoid update () {}}

Run, the scene is still generated very perfect, in the processing of binary parsing need to pay special attention to the byte alignment, because all your data is actually a byte[] byte array, you need a rational and orderly byte array to split, and then converted to the corresponding data, so be sure to align otherwise it will be wrong.

And finally put the code out.

: Http://vdisk.weibo.com/s/la_QE

(turn) Unity3d Research Institute export the scene XML or JSON or binary and parse the restore scene

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.