Export the unity scene as a configuration file

Source: Internet
Author: User

When dealing with a lot of people involved in the project, many times in the operation of the scene, may be involved in the scene modification conflict, this time, we can save the scene as a configuration file (Cocos scene, Android View saving idea), can be used json/xml/ Binary and other ways to store, at this time, we need to scenes all the gameobject in the form of prefab storage, and take into account the Prefab component reference problem, you need to drag the original directly into the possession of the game object to acquire, to find/ Findtag this type of method to initialize (a question that may be faced is: what kind of list is it originally held?). This question has not yet been thought of as a good solution.

In the storage, the main use of XML to store, for each gameobject (Prefab), only need to store their localposition,localrotation,localscale,parentpath and other information. The main ideas and design are mainly related to the above mentioned content. Directly below the program:

Using Unityengine;
Using Unityeditor;
Using System.Collections;
Using System.Collections.Generic;
Using System.Xml;
Using System.IO;

http://www.xuanyusong.com/archives/1919
public class Exportscene:editor
{
Export all game scenes to XML format
[MenuItem ("Gameobject/exportscene2xml")]
static void Exportscene2xml ()
{
String Tfilepath = Application.datapath + @ "/resources/xml/scenes.xml";
if (! File.exists (Tfilepath))
{
File.delete (Tfilepath);
}
XmlDocument xmldoc = new XmlDocument ();
XmlElement root = Xmldoc.createelement ("allgameobjects");

ilist<int> exportedgameobjectuniqueidlst = new list<int> ()///Loaded prefab ID information, anti-duplication

//Traverse all game scenes
foreach (Unityeditor.editorbuildsettingsscene S in UnityEditor.EditorBuildSettings.scenes)
{
if (s.enabled)
{
String tscenename = S.path;
Editorapplication.openscene (Tscenename);
XmlElement tscenesroot = xmldoc.createelement ("Scenes");
Tscenesroot.setattribute ("Scenename", tscenename);
list<gameobject> tlst = new list<gameobject> ();
Tlst.adds ((gameobject[)) Object.findobjectsoftype (typeof (Gameobject)));
for (int i = tlst.count-1; I >= 0; i--)
{
Gameobject obj = tlst[i];//Here The logic is not yet optimized
if (obj = = null)
{
continue;
}
Gameobject tprefab = Prefabutility.findrootgameobjectwithsameparentprefab (obj);//prefab whole
int corresponding to the current object Tuniqueid = Tprefab.getinstanceid ();
if (Exportedgameobjectuniqueidlst.contains (Tuniqueid))
{
continue;
}
Exportedgameobjectuniqueidlst.add (Tuniqueid);


if (prefabutility.getprefabtype (tprefab) = = Prefabtype.none)
{
Debug.logerror ("Noneprefab =" + Tprefab) ;//Active becomes prefab (whole as a prefab ———— > prompt manual processing (there are prefab and non-prefab parent-Child hierarchy issues!! )
//prefabutility.createprefab (@ "assets/resources/sceneprefabs/" + Tprefab.name + @ ". Prefab", Tprefab);
}

Stack<gameobject> tstack = Getparentprefabqueue (Tprefab);
Gameobject tobj = null;
if (Tstack.count > 0)
{
Tobj = Tstack.pop ();
}
XmlElement tparent = tscenesroot;
while (tobj! = null)
{
//Find out if the node exists
XmlElement telement = Getxmlelementbyid (xmldoc, Tobj.getinstanceid () . ToString ());
if (null = = TElement)
{
Tparent = Generatenode (xmldoc, ref tparent, tobj);
}
Else
{
Tparent = telement;
}
if (Tstack.count > 0)
{
Tobj = Tstack.pop ();
}
Else
{
Tobj = null;
}
}
//xmlelement tchild = Generatenode (xmldoc, ref tscenesroot, tprefab);
Root. AppendChild (Tscenesroot);
Xmldoc.appendchild (root);
Xmldoc.save (Tfilepath);
}
}
}
//Refresh Project View
Assetdatabase.refresh ();
}

The XML node of the child object is placed below the parent object
private static XmlElement Generatenode (XmlDocument _xmldoc, ref XmlElement _parent, Gameobject _prefab)
{
XmlElement tgameobject = _xmldoc.createelement ("Gameobject");
Tgameobject.setattribute ("ID", _prefab. Getinstanceid (). ToString ());
Tgameobject.setattribute ("Name", _prefab.name);
Tgameobject.setattribute ("Asset", _prefab.name + ". Prefab");
String trootpath = Getrootpath (_prefab);
if (!trootpath.equals (""))
{
Tgameobject.setattribute ("RootPath", Trootpath);
}

#if true
Vector3 TPos = _prefab.transform.localposition;
if (! mathf.approximately (tpos.x, 0))//position 0 as default, do not have to store
{
Tgameobject.setattribute ("Px", Tpos.x.tostring ("0.###"));
}
if (! mathf.approximately (tpos.y, 0))
{
Tgameobject.setattribute ("Py", Tpos.y.tostring ("0.###"));
}
if (! mathf.approximately (tpos.z, 0))
{
Tgameobject.setattribute ("Pz", Tpos.z.tostring ("0.###"));
}
#endif

#if true
Vector3 tangle = _prefab.transform.localrotation.eulerangles;
if (! mathf.approximately (tangle.x, 0))//Angle 0 as default, no need to store
{
Tgameobject.setattribute ("Rx", Tangle.x.tostring ("0.###"));
}
if (! mathf.approximately (tangle.y, 0))
{
Tgameobject.setattribute ("Ry", Tangle.y.tostring ("0.###"));
}
if (! mathf.approximately (tangle.z, 0))
{
Tgameobject.setattribute ("Rz", Tangle.z.tostring ("0.###"));
}
#endif

#if true
Vector3 TScale = _prefab.transform.localscale;
if (! Mathf.approximately (tscale.x, 1))//scale is 1 as the default value and does not have to be stored
{
Tgameobject.setattribute ("Sx", Tscale.x.tostring ("0.###"));
}
if (! Mathf.approximately (TSCALE.Y, 1))
{
Tgameobject.setattribute ("Sy", Tscale.y.tostring ("0.###"));
}
if (! Mathf.approximately (TSCALE.Z, 1))
{
Tgameobject.setattribute ("Sz", Tscale.z.tostring ("0.###"));
}
#endif
_parent. AppendChild (Tgameobject);
return tgameobject;
}

//Get node based on ID
private static XmlElement Getxmlelementbyid (XmlDocument _xmldoc, string _id)
{
XmlNode troot = _ Xmldoc.selectsinglenode ("allgameobjects");
if (null! = Troot)
{
XmlNodeList nodeList = troot.childnodes;
XmlNode scene = null;
for (int i = 0; i < Nodelist.count; i++)
{
scene = Nodelist[i];
XmlNode gameobject = null;
for (int j = 0; j < scene. Childnodes.count; J + +)
{
Gameobject = scene. CHILDNODES[J];
XmlElement Tret = Getxmlelementbyid (_xmldoc, Gameobject, _id);
if (Tret! = null)
{
return tret;
}
}
}
}
return null;
}

private static XmlElement Getxmlelementbyid (XmlDocument _xmldoc, XmlNode _gameobject, string _id)
{
XmlElement Tret = null;
if (((XmlElement) _gameobject). GetAttribute ("ID"). Equals (_ID)//Judge current node
{
Tret = (XmlElement) _gameobject;
}
else if (_gameobject.childnodes.count > 0)//recursive Find child nodes
{
XmlNode gameobject = null;
for (int i = 0; i < _gameobject.childnodes.count; i++)
{
Gameobject = _gameobject.childnodes[i];
Tret = Getxmlelementbyid (_xmldoc, Gameobject, _id);
if (Tret! = null)
{
Break
}
}
}
return Tret;
}

private static string Getrootpath (Gameobject _obj)
{
String tResult = "";
Transform tparent = _obj.transform.parent;
while (tparent! = null)
{
if (Tresult.equals (""))
{
TResult = Tparent.name;
}
Else
{
TResult = Tparent.name + "/" + TResult;
}
Tparent = tparent.parent;
}
return tResult;
}

Search by ID First, whether the node exists
private static stack<gameobject> Getparentprefabqueue (Gameobject _obj)
{
ilist<int> tuniqueidlst = new list<int> ();
stack<gameobject> tstack = new stack<gameobject> ();
Tstack.push (_obj);
Tuniqueidlst.add (_obj. Getinstanceid ());
Transform tparent = _obj.transform.parent;
Gameobject tprefab = null;
while (tparent! = null)
{
Tprefab = Prefabutility.findrootgameobjectwithsameparentprefab (Tparent.gameobject);
int tID = Tprefab.getinstanceid ();
if (!tuniqueidlst.contains (TID))
{
Tstack.push (Tprefab);
Tuniqueidlst.add (TID);
}
Tparent = tparent.parent;
}
return tstack;
}


}

Based on the generated XML configuration file and the prefab information under resources, the logic for generating the scenario is as follows:

public class Generatescenefromxml
{
#region
private static readonly Object lockhelper = new Object ();
Private Generatescenefromxml ()
{
}
private static Generatescenefromxml instance = NULL;
public static Generatescenefromxml Instance
{
Private Set
{
}
Get
{
if (null = = instance)
{
Lock (Lockhelper)
{
if (null = = instance)
{
Instance = new Generatescenefromxml ();
}
}
}
return instance;
}
}
#endregion Singleton

public void Init ()
{
Textasset Tasset = resources.load<textasset> ("Xml/scenes");
XmlDocument xmldoc = new XmlDocument ();
Xmldoc.loadxml (Tasset.text);

XmlNodeList nodeList = Xmldoc.selectsinglenode ("Allgameobjects"). ChildNodes;
XmlNode scene = null;
for (int i = 0; i < Nodelist.count; i++)
{
Scene = Nodelist[i];
XmlNode gameobject = null;
for (int j = 0; j < scene. Childnodes.count; J + +)//Traverse all game objects under the scene
{
Gameobject = scene. CHILDNODES[J];
Generaterecursivily (Gameobject);
}
}
Resources.unloadasset (Tasset);
}

Builds itself, and recursively generates sub-objects in turn
Private Gameobject generaterecursivily (XmlNode _node, Transform _parent = null)
{
Vector3 TPos = Vector3.zero;
Vector3 tRot = Vector3.zero;
Vector3 TScale = Vector3.one;

XmlElement TElem = ((XmlElement) _node);
Tpos.x = float. Parse (Telem.getattributevalue ("Px", "0"));
Tpos.y = float. Parse (Telem.getattributevalue ("Py", "0"));
Tpos.z = float. Parse (Telem.getattributevalue ("Pz", "0"));

Trot.x = float. Parse (Telem.getattributevalue ("Rx", "0"));
Trot.y = float. Parse (Telem.getattributevalue ("Ry", "0"));
Trot.z = float. Parse (Telem.getattributevalue ("Rz", "0"));

tscale.x = float. Parse (Telem.getattributevalue ("Sx", "1"));
Tscale.y = float. Parse (Telem.getattributevalue ("Sy", "1"));
Tscale.z = float. Parse (Telem.getattributevalue ("Sz", "1"));

String tasset = "sceneprefabs/" + telem.getattribute ("Name");
Gameobject tobj = (gameobject) gameobject.instantiate (Resources.load (Tasset));
TObj.transform.parent = _parent;
if (Telem.getattributevalue ("RootPath", ""). Equals (""))
{
TObj.transform.parent = null;
}
Else
{
TObj.transform.parent = Gameobject.find (Telem.getattribute ("RootPath")). Transform;
}
TObj.transform.localPosition = TPos;
TObj.transform.localEulerAngles = TRot;
TObj.transform.localScale = TScale;
Tobj.name = Telem.getattribute ("name");//Remove "(Clone)"

if (_node. HasChildNodes)
{
for (int i = _node. childnodes.count-1; I >= 0; i--)
{
Generaterecursivily (_node. Childnodes[i], tobj.transform);
}
}
return tobj;
}
}

Of course, the storage efficiency of XML is not so high that it can be adjusted to json/binary storage mode.

Export the unity scene as a configuration file

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.