How to Read an XML File in Unity

kristielAll Topics, Tutorial, Unity Game Development

Share this Post

I recently started working on a project in Unity 3D that makes use of an XML file to load data into the game. Being relatively new to game design, I had to do a lot of research to figure out how to load the XML file and assign that data in a usable way. I have gotten things working in the game and thought I would write a post that details how to read XML data and use it in Unity using C#. What I will cover is how to read the data from XML using C# and how to assign that data to a List so that it can be used elsewhere in your program. This is, essentially, the very basics of reading an XML file in Unity.

Options for Reading an XML file in Unity

The first thing I want to point out is that there are several different ways that this can be accomplished.

XMLReader Class: A lot of people have recommended using the XMLReader class, which provides noncached, forward-only access to XML data. From what I have read, this is the low-cost way of grabbing XML data. It provides the lowest performance hit in your program.

XMLDocument Class: There is also the XMLDocument Class. I know very little about this class and I ran into very few people advocating for its use within Unity3D.

XDocument Class: Lastly, there is the XDocument class, which is what I ended up using and what I will be using in this post. Admittedly, I primarily chose it because it seemed to be the most well-documented in the Unity realm. In the future, I hope to explore the XMLReader option more thoroughly since it is considered the most performance-efficient.

STEP 1 – Create XML File

First of all, you need to have an XML file in your Unity project. You can use a program like Notepad++ to create XML files. Here are the contents of a test file I am using. You can copy and paste it into your XML editor and save the file if you want:

<?xml version=”1.0″ encoding=”UTF-8″ standalone=”yes”?>

<chapter_1 xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”>

<page number = “1”>

<name>Mark</name>

<dialogue>This is a test!</dialogue>

</page>

<page number = “2”>

<name>Tony</name>

<dialogue>This is a second test.</dialogue>

</page>

<page number = “3”>

<name>Carol</name>

<dialogue>This is a third test.</dialogue>

</page>

<page number = “4”>

<name>Kristie</name>

<dialogue>This is a fourth test.</dialogue>

</page>

<page number = “5”>

<name>Jeff</name>

<dialogue>This is a fifth test.</dialogue>

</page>

<page number = “6”>

<name>Frank</name>

<dialogue>This is a sixth test.</dialogue>

</page> </chapter_1>

STEP 2 – Add XML file to Unity

Once you have the file created, you will need to put it somewhere in your Unity project. I put mine inside Assets/Resources/XML Files.

STEP 3 – Create Loader scene

Now, inside of Unity, the first thing I did was create a Loader scene that contains a Loader game object, which will be used to load the XML file, read all the data, and assign that data to a List that I can use in my game. So do this:

  • Create a new scene called TestScene. TestScene can remain empty.
  • Save TestScene and create a new scene in Unity. This will be your Loader scene. Create an empty game object in your hierarchy. Call it whatever you want.
  • On the empty game object, add a new C# script as a component. Name it whatever you want. I named mine Loader. Open the script in MonoDevelop (or whatever IDE you use)

My Loader scene looks like this:

STEP 4 – Add Coding

Once you have the Loader script open in your IDE, copy and paste this code (I apologize if the formatting is messed up). I have provided comments to explain the logic behind everything:

using UnityEngine;

using System.Collections;

using System.Collections.Generic; //Needed for Lists

using System.Xml; //Needed for XML functionality

using System.Xml.Serialization; //Needed for XML Functionality

using System.IO;

using System.Xml.Linq; //Needed for XDocument

public class Loader : MonoBehaviour {

XDocument xmlDoc; //create Xdocument. Will be used later to read XML file IEnumerable<XElement> items; //Create an Ienumerable list. Will be used to store XML Items. List <XMLData> data = new List <XMLData>(); //Initialize List of XMLData objects.

int iteration = 0, pageNum = 0;

string charText, dialogueText;

bool finishedLoading = false;

void Start ()

{

DontDestroyOnLoad (gameObject); //Allows Loader to carry over into new scene LoadXML (); //Loads XML File. Code below. StartCoroutine (“AssignData”); //Starts assigning XML data to data List. Code below

}

void Update ()

{

if (finishedLoading)

{

Application.LoadLevel (“TestScene”); //Only happens if coroutine is finished finishedLoading = false;

}

}

void LoadXML()

{

//Assigning Xdocument xmlDoc. Loads the xml file from the file path listed. xmlDoc = XDocument.Load( “Assets/Resources/XML Files/circles_test.xml” );

//This basically breaks down the XML Document into XML Elements. Used later. items = xmlDoc.Descendants( “page” ).Elements ();

}

//this is our coroutine that will actually read and assign the XML data to our List IEnumerator AssignData()

{

/*foreach allows us to look at every Element of our XML file and do something with each one. Basically, this line is saying “for each element in the xml document, do something.

*/ foreach (var item in items)

{

/*Determine if the <page number> attribute in the XML is equal to whatever our current iteration of the loop is. If it is, then we want to assign our variables to the value of the XML Element that we need.

*/

if(item.Parent.Attribute(“number”).Value == iteration.ToString ())

{

pageNum = int.Parse (item.Parent.Attribute (“number”).Value); charText = item.Parent.Element(“name”).Value.Trim (); dialogueText = item.Parent.Element (“dialogue”).Value.Trim ();

/*Create a new Index in the List, which will be a new XMLData object and pass the previously assigned variables as arguments so they get assigned to the new object’s variables.

*/

data.Add (new XMLData(pageNum, charText, dialogueText));

/*To test and make sure the data has been applied to properly, print out the musicClip name from the data list’s current index. This will let us know if the objects in the list have been created successfully and if their variables have been assigned the right values.

*/

Debug.Log (data[iteration].dialogueText);

iteration++; //increment the iteration by 1

}

}

finishedLoading = true; //tell the program that we’ve finished loading data. yield return null;

}

}

// This class is used to assign our XML Data to objects in a list so we can call on them later. public class XMLData {

public int pageNum;

public string charText, dialogueText;

// Create a constructor that will accept multiple arguments that can be assigned to our variables. public XMLData (int page, string character, string dialogue)

{

pageNum = page;

charText = character;

dialogueText = dialogue;

}

}

STEP 5 – Test

Now, if you play the Loader scene, all the data in the XML file should get loaded. If you’re using the XML data I provided, you should see something like this in your console:

Unity XML Testing

This confirms that our List has been populated with the appropriate number of objects with each one containing unique information as per each page number. Also, you may not notice it if your TestScene has nothing special in it, but your Loader object should carry over into the new level so you can call on the data whenever you need to. In my hierarchy in the following screenshot, you’ll see all the items in my TestScene loaded alongside my Loader object:

Unity TestScene Loader

Understanding Element vs. Attribute

One thing I had difficulty with when I first started working with XML files was the difference between an Element and an Attribute. This kind of code can be very confusing if you don’t learn what some of this terminology means. An element is, essentially, a tag in an XML file. So, my <name> tag is technically an element. Whatever that element contains is the data that is in between the <name> and </name> tags. So, when I call item.Parent.Element(“name”).Value, I’m calling on the value contained between the <name> and </name> tags. Elements are different than Attributes. Attributes are variables that are assigned values within an element. For example: <page number = “1”> In this example, “number” is an attribute of the “Page” Element. I use this attribute as an if statement to determine which page our for each loop is reading. Within that if statement, I assign our variables the values that are contained within that specific page number. This works because the if statement only executes if our current iteration of the loop is looking within the specific page number that I want.

Additional Info: Sound and Text

In my game, I’m also using it to load AudioClip files for music and sound effects using lines like this:

musicClip = Resources.Load (“Music/” + item.Parent.Element (“music”).Value.Trim ().ToString ()) as AudioClip;

I’ve also written text from an XML document straight into a Text UI object like this:

foreach ( var name in names )

{

// is the element named “name” and is it a child of the current page number?

if(name.Name == “name” && name.Parent.Attribute(“number”).Value ==

pageNum.ToString ())

{

nameUI.text = name.Value.Trim ();

}

}

Conclusion

In conclusion, this is a rather primitive example of XML Reading. Hopefully it can serve as a starting point for anybody who may be starting off in this realm. Once you understand the basics of XML reading in Unity, you can further refine your code and create an incredibly dynamic system. I hope this helps you adding an XML file in Unity. Please feel free to leave comments or feedback on the article. I am sure there are areas where I could be doing this more efficiently. Programming is a collaborative effort so please feel free to leave a comment and discuss what could be done differently or how this could be implemented in a different way. Thank you!

Blogger: Mark Philipp, Application Engineer at Studica

Share this Post