- Home /
Serializing GameObject Data with XML, Adaptation
(Apologies for the large code dump but it's imperative i show every edit I've made to the original source code in an attempt to adapt it.) I'm desperately trying to find a way of serializing gameobject data in a 2D game where the player can place objects and build buildings. After alot of failed attempts and research i discovered this code in this question on the forums provided by @TonyLi and @Slimy619. It works perfectly for serializing ONE gameobject and one gameobject only, but whenever i try to adapt it to handle more than one specific type, they all revert immediately back to the ONE gameobject the system is designed to handle.
My Question is - How do i adapt this code to handle more than one type of GameObject? Here's what i've tried so far and the issues i've identified; (C#)
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
//using System.Xml;
using System.Xml.Serialization;
using System.IO;
//using System.Text;
public class SaveLoadSystem : MonoBehaviour {
public GameObject CubeContainer;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
public class CubeInfo
{
public string prefabName;
public Vector3 position;
//public Quaternion rotation;
public CubeInfo()
{
}
public CubeInfo(Transform cube )
{
prefabName = cube.name.Replace("(Clone)", string.Empty);
position = cube.position;
//rotation = cube.rotation;
}
}
public class HigInfo
{
public string prefabName2;
public Vector3 position2;
public HigInfo()
{
}
public HigInfo(Transform Hig)
{
prefabName2 = Hig.name.Replace("(Clone)", string.Empty);
position2 = Hig.position;
}
}
public class BuildingInfo
{ // Stores info about all the cubes.
// Make a List holding objects of type CubeInfo
public List<CubeInfo> cubeList;
public List<HigInfo> HigList;
public BuildingInfo()
{
// Make a new instance of the List "cubeList"
}
public BuildingInfo(GameObject rootObject)
{
cubeList = new List<CubeInfo>();
HigList = new List<HigInfo>();
foreach (Transform child in rootObject.transform)
{
cubeList.Add (new CubeInfo(child));
print (child);
}
foreach (Transform child in rootObject.transform)
{
HigList.Add (new HigInfo(child));
print (child);
}
}
public void reload(GameObject rootObject)
{
// Rebuild the cubes after loading building info:
foreach (var cubeInfo in cubeList)
{
GameObject cube = Instantiate(Resources.Load(cubeInfo.prefabName),cubeInfo.position, Quaternion.identity) as GameObject;
cube.transform.parent = rootObject.transform;
}
foreach (var HigInfo in HigList)
{
GameObject Hig = Instantiate(Resources.Load(HigInfo.prefabName2),HigInfo.position2, Quaternion.identity) as GameObject;
Hig.transform.parent = rootObject.transform;
}
}
}
void Save(GameObject rootObject, string filename)
{
BuildingInfo buildingInfo = new BuildingInfo(rootObject);
XmlSerializer serializer = new XmlSerializer(typeof(BuildingInfo));
TextWriter writer = new StreamWriter(filename);
serializer.Serialize(writer, buildingInfo);
writer.Close();
print ("Objects saved into XML file\n");
}
void Load(GameObject rootObject, string filename)
{
// while(rootObject.transform.GetChildCount()>0)
// {
// GameObject.Destroy(rootObject.transform.GetChild (0));
// }
XmlSerializer serializer = new XmlSerializer(typeof(BuildingInfo));
TextReader reader = new StreamReader(filename);
BuildingInfo buildingInfo = serializer.Deserialize(reader) as BuildingInfo;
buildingInfo.reload(rootObject);
reader.Close();
print ("Objects loaded from XML file\n");
}
void OnGUI()
{
if (GUI.Button (new Rect (30, 60, 150, 30), "Save State"))
{
Save (CubeContainer, "savefile.xml");
}
if (GUI.Button (new Rect (30, 90, 150, 30), "Load State"))
{
Load (CubeContainer, "savefile.xml");
}
}
}
Using the Debug lines for (child) reveals in the inspector console window that the items are all being saved as "cube", in spite of the additions i've made. I've tried similarly including a Cube2 field and all the relevant parameters throughout the file without making a second cubeinfo (higinfo) class to no avail. The Hig gameobject in my resources folder merely gets renamed to cube and the game spawns instances of the first gameobject on Load. I am completely stumped. I haven't come across any other working method for saving instantiated gameobjects, If it's worth anything all i need to save is the location (vector3) sprite and collider of the object. Also worth mentioning this game is intended for PC and Android if its worth anything. I'd appreciate any possible insight anyone could offer.
Before saving-
After loading-
Hi @I_CAST_FIST,
I just wanted to make some clarifications.
The code that I posted can be used to save the name and location of more than one GameObject. In fact, it is exactly what I used it for. The GameObject called "Cube Container" is actually an empty gameobject and acts as a container where I dump in all the GameObjects (Different Cubes in my case) that I need to save. So, in reality, all the gameobjects I want to save are declared as the children of the cube container. When I press "save", the program iterates through the children of the Cube Container and saves their names and location in an X$$anonymous$$L file, regardless of the type, material, colour etc. of the gameobjects.
Having said that, there are far more simpler ways of saving gameobjects, depending upon the type of program/game you are developing. $$anonymous$$y program required a predeclared grid, therefore, I could have saved each gameobject as a specific number inside a text file. And then load the text file back and instantiate the objects back at their appropriate grid points.
For example, if # represents a boundary object, 8 represents a wall object and 0 represents free space, then I could have saved the map in a 20x10 grid as shown below:
####################
#000000880000000000#
#000000888888000000#
#000000888888000000#
#000000000088000000#
#008888888888000000#
#008888888888000000#
#008800000000000000#
#008800000000000000#
####################
But I used the X$$anonymous$$L serializer ins$$anonymous$$d, because at the time, I wasn't as skilled in program$$anonymous$$g and had to meet the deadline. $$anonymous$$oreover, PlayerPrefs() was not a viable option since I needed to save a lot of gameobjects in a readable save file. Therefore, if PlayerPrefs works for you, then go with that ins$$anonymous$$d.
Hope I was able to be of some help.
Thankyou both for the quick replies, seriously O_o I corrected it following a mistake tony pointed out i'd forgotten to consider, the entire game is grid based from the building, to the combat, but i managed to implement it all without actually making any form of grid system and just careful maths haha.
The entire game world $$anonymous$$us some dungeons is editable, it would be something of a 600x600 grid at this point in time with a possible 1200 something gameobjects needing to be saved and reloaded. I'm much under the same circumstance, first year of program$$anonymous$$g at uni and trying to complete a summer project before I leave home for a while :) nearly done
Answer by TonyLi · Jul 25, 2015 at 05:24 PM
If you only need to save the prefab name and location, why not a simple text file where each line is something like:
name,x,y,z
I'm not sure exactly what you intend with Cube and Hig, but are you sure your BuildingInfo data structure is being generated correctly? The first loop in BuildingInfo(rootObject) will add all children to the cube list. Do you only want to add cubes? If so, maybe you need to identify the types of all children and only add the ones that are cubes.
To stick with XML, check the XML tutorial on the wiki.
There's also UnitySerializer, which may work for you, and you wouldn't have to maintain any custom code.
Days like this really put it into perspective how much of a beginner i am still, even at the end of this project. I added
if( child.gameObject.name == "hig(Clone)")
for the two types of gameobject respectively in the BuildingInfo section and corrected a horrific mistake i made following your advice, i was setting the name of all the objects i instantiated as "cube" by accident in the file that handles my spawning. I am an idiot, and now it works perfectly, im off to go set it up for my other 74 spawn types. Thankyou very much for your time :P
Regarding The UnitySerializer, i had toyed around with it but the original authors Whydoidoit's website is down and with it all the documentation on how to use it gone, the wizard wasn't saving objects that were instantiated in game and i had no reference points on how to proceed :s I also needed to save the object components collider and script.
No worries; this kind of thing slips by all of us at times! :-)
Answer by Voxel-Busters · Aug 08, 2015 at 03:04 AM
You can save the trouble, by serializing GameObject using Runtime Serialization for Unity. Its not just another serialization plugin which works only on custom c# objects. But what makes it special is its capablity to serialize Unity Objects like GameObject, MonoBehaviours, Textures, Prefabs etc. As a matter of fact, you can even use it for Scene Serialization. For more info about supported list, please check this link.