Tag Archives: XmlDocument

Saving and Loading Level Data in Unity

This describes a method of persisting data in Unity. For example, saving and loading the current game level.

The first thing that you will need is to create a helper class to read and write the data that you need:

        public static void SaveGameState()
        {
            XmlDocument xml = new XmlDocument();
            var el = xml.CreateElement("PlayerStatus");
            el.SetAttribute("CurrentLevel", Application.loadedLevel.ToString());
            xml.AppendChild(el);
            xml.Save("data.xml");
        }

        public static void LoadGameState()
        {
            XmlDocument xml = new XmlDocument();
            xml.Load("data.xml");
            var el = xml.GetElementsByTagName("PlayerStatus")[0];
            string currentLevel = el.Attributes["CurrentLevel"].Value;
            int loadLevel = 0;
            if (!string.IsNullOrEmpty(currentLevel))
            {
                loadLevel = int.Parse(currentLevel);
                if (Application.loadedLevel != loadLevel)
                    Application.LoadLevel(loadLevel);
            }
        }

The next stage is to plug this into Unity. I put the following in a Master Script (which is essentially just a script associated with an empty game object).

    void OnApplicationQuit()
    {
        GameState.SaveGameState();       
    }

    void Start()
    {
        GameState.LoadGameState();
    }

I’ve seen plenty of articles on using serialisation for this, and that would obviously have the same effect, but this is another option.

Reading an XML Document using XmlDocument

I recently saw a question on SO relating to this, and pretty much every answer was: “Use LINQ To Xml”. Which is good advice. If you don’t want to do that (for whatever reason), then you may decide to use an approach such as the following.

Disclaimer

I am not stating that this is the best was to accomplish this, merely that it is a way. I am also not asserting that any of the books mentioned exist in the libraries they are listed under.

The Code

Declare the XML string here. Note; if you intend to read this from a file then just call Xml.Load() later on, instead of LoadXml.

        static string xmlDoc =
            @"<RootNode>
                <Library Name='Manchester'>
                    <Book>
                        <Title>Fly Fishing</Title>
                        <Author>J. R. Hartley</Author>
                        <Floor>1</Floor>
                    </Book>
                    <Book>
                        <Title>To Kill A Mockingbird</Title>
                        <Author>Harper Lee</Author>
                        <Floor>3</Floor>
                    </Book>
                </Library>
                <Library Name='London'>
                    <Book>
                        <Title>1984</Title>
                        <Author>George Orwell</Author>
                        <Floor>2</Floor>
                    </Book>
                </Library>
            </RootNode>";

Load the document:

            XmlDocument xml = new XmlDocument();
            xml.LoadXml(xmlDoc);
            XmlNodeList nodes = xml.ChildNodes;
            ReadXmlNodes(nodes);

            Console.ReadLine();

And traverse it:

        /// <summary>
        /// Traverse the XML node and print the values
        /// </summary>
        /// <param name="nodes"></param>
        private static void ReadXmlNodes(XmlNodeList nodes)
        {
            foreach (XmlNode node in nodes)
            {
                // Omit #text nodes
                if (node.NodeType != XmlNodeType.Text)
                {
                    Console.WriteLine(node.Name);
                }

                // Check if there are any attributes and, if so, print them now
                if (node.Attributes != null)
                {
                    PrintAttributes(node);
                }

                // If the node is a parent then recurively call the function
                if (node.HasChildNodes)
                {
                    ReadXmlNodes(node.ChildNodes);
                }
                // Otherwise just print the value
                else
                {
                    Console.WriteLine("Node Value: {0}", node.Value);
                }
            }

        }

        /// <summary>
        /// Print all the attributes for a node
        /// </summary>
        /// <param name="node"></param>
        private static void PrintAttributes(XmlNode node)
        {
            foreach (XmlAttribute att in node.Attributes)
            {
                Console.WriteLine("Attribute: {0}", att.Value);
            }
        }
    }