Save/load a gameobject to an external file.

Hi, I need some help making or finding a save/load solution. I need it to be able to save one gameObject from one scene, and then load it into another scene. the said gameobject will have up to 8 children, and the children will have children. I need to save all of them, that includes position, rotation, and what its parent is. The number of children is dependent on how the player constructs the gameobject. I would prefer to save the data to a external file so that it can easily be shared between players. Is there any simple or atleast workable way to do this?

Goat,

What you want is called a ‘serializer.’

They come in a lot of different flavors. Do you want the file to be human readable? If so, then you’re looking for an XML or JSON serializer. If you’re after JSON, You’re best bet there is trying the Unity Serializer. If you have to have XML, then do some googling for Unity XMLSerializer, it isn’t too hard to figure out.

If it’s going to be a large file, or you want to keep users from making changes to it, then a binary format is what you want (This won’t stop a really determined user, but will deter most). Mono comes with a class to do this, it’s called BinaryFormatter. There is also a C# library for Google’s Protocol Buffer format (it’s called protobuf-net). It tends to be faster and produce smaller files. If this is the route you want to take, I recently wrote a serializer using protbuf-net, and I’d be more than happy to share it.

Cheers,
Cahman

Hey Cahman
thanks for the reply. yes it would be awesome if I can have a look at your serializer. would you be able to help me if i have any further questions? Right now this is the biggest challenge i have with what i’m trying to do.

Goat,

I think you’ll have the most success with Unity Serializer. It’s well documented and has a friendly interface.

If you must have XML, the code below is a very simple serialize/deserialize and test class.

If you must have it in a binary format, I wrote up a tutorial on my website for using protobuf-net or the mono binary formatter.

Static XML Serializer

/*!**********************************************
 * XMLSerializer.cs
 * 18 April 2013
 * V 1.0
 * Cahman Games
 * www.cahman.com
 * 
 * 
 * Provides static functions for 
 * 1) serializing to XML then saving playerprefs
 * 2) serializing to XML, then saving to a local file
 * 3) serializing to XML, then sending to a web address
 * 
 *
 *************************************************/
/***************************************************
 * LICENSE:
 * Copyright (c) 2013 CahmanGames www.cahman.com
 * 
 * This software is provided 'as-is', without any express or implied
 * warranty. In no event will the authors be held liable for any damages
 * arising from the use of this software.
 * 
   **************************************************************/

using UnityEngine;
using System.Collections.Generic;
using System.Xml.Serialization;
using System.IO;
using System;

public static class UnityXMLSerializer{
	
	private static System.Type[] extraSerializeTypes;
	
	//public static void SetupSerializer(System.Type[] serializeTypes)
	//{
	//	serializer = new XmlSerializer(
		
	
	/// <summary>
	/// Serialize an object to an xml file.
	/// </summary>
	/// <returns>
	/// True if written, false if file exists and overWrite is false
	/// </returns>
	/// <param name='writePath'>
	/// Where to write the file.  Consider using Application.PersistentData
	/// </param>
	/// <param name='serializableObject'>
	/// The Object to be serialized.  The generic needs to be the type of the object to be serialized
	/// </param>
	/// <param name='overWrite'>
	/// If set to <c>true</c> over write the file if it exists.
	/// </param>
	public static bool SerializeToXMLFile<T>(string writePath, object serializableObject, bool overWrite = true)
	{
		if(File.Exists(writePath)  overWrite == false)
			return false;
		XmlSerializer serializer = new XmlSerializer(typeof(T));
		using( var writeFile = File.Create(writePath))
		{
			serializer.Serialize(writeFile, serializableObject);
		}
		return true;
	}
	
	/// <summary>
	/// Deserialize an object from an XML file.
	/// </summary>
	/// <returns>
	/// The deserialized list.  If the file doesn't exist, returns the default for 'T'
	/// </returns>
	/// <param name='readPath'>
	/// Where to read the file from.
	/// </param>
	/// <typeparam name='T'>
	/// Type of object being loaded from the file
	/// </typeparam>
	public static T DeserializeFromXMLFile<T>(string readPath)
	{
		if(!File.Exists (readPath))
			return default(T);
		
		XmlSerializer serializer = new XmlSerializer(typeof(T));
		
		using (var readFile = File.OpenRead (readPath))
			return (T)serializer.Deserialize(readFile);
		
		
	}
	
		
	
	

}

Simple Test Class

/*!**********************************************
 * XMLSerializerTest.cs
 * 23 April 2013
 * V 1.0
 * Cahman Games
 * www.cahman.com
 * 
 * 
 * Test the XML serializer
 * 
 *
 *************************************************/
/***************************************************
 * LICENSE:
 * Copyright (c) 2013 CahmanGames www.cahman.com
 * 
 * This software is provided 'as-is', without any express or implied
 * warranty. In no event will the authors be held liable for any damages
 * arising from the use of this software.
 * 
   **************************************************************/

using UnityEngine;
using System.Collections;
using System;
using System.Xml;
using System.Xml.Serialization;
using System.Collections.Generic;

public class UnityXMLSerializerTest : MonoBehaviour {
	
	List<BaseClass> thingsToSave = new List<BaseClass>();
	
	// Use this for initialization
	void Start () {
		
		BaseClass firstVariable = new BaseClass();
		DerivedClass1 SecondVariable = new DerivedClass1();
		DerivedClass2 thirdVariable = new DerivedClass2();
		
		thingsToSave.Add(firstVariable);
		thingsToSave.Add(SecondVariable);
		thingsToSave.Add(thirdVariable);
		
		UnityXMLSerializer.SerializeToXMLFile<List<BaseClass>>("Test.xml", thingsToSave, true);
		
	
	}
	
	// Update is called once per frame
	void Update () {
	
	}
}


[Serializable()]
//Tell the serializer about derived classes
[XmlInclude(typeof(DerivedClass1))]
[XmlInclude(typeof(DerivedClass2))]
public class BaseClass
{
	public int paramterToSave = 5;
	
	[XmlIgnoreAttribute]
	public int parameterToIgnore = 7;
}


public class DerivedClass1: BaseClass
{
	[XmlElement("other")]
	public string differentName = "This element should be named 'other' in the xml file";

}


public class DerivedClass2 : BaseClass
{
	public bool usefulField = false;
}

If you have specific questions, I’ll try my best to help.

Cheers,
Cahman