Ok, I had a hell of a time figuring out how to load in XML for a Unity project I’m working on and use it to build a level. Fortunately the Unity Community is vibrant and helpful, even though you may have to do digging to find what you’re looking for. It can be difficult getting started, especially when working in C# as many of the examples are coded in Javascript.

Here’s an example of some game xml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<stageData>

<stage>

<map>1, 2, 3, A, B, C</map>

<map>4, 5, 6, 7, 8, 9</map>

<map>2, 1, 3, 5, 6, 2</map>

</stage>

<map>0, 0, 0, 0, 0, 0</map>

<map>1, 1, 1, 1, 1, 1</map>

<map>A, A, A, A, A, A</map>

<map>3, 3, 3, 3, 3, 3</map>

<map>C, C, C, C, C, C</map>

</stage>

</stageData>

Keep in mind that there’s a million ways to go about doing this. I tried to justify why I did it this way, and the best I can say is “I just felt like it.” Haha!

I ended up using a C# port of this Lightweight XML parser. The benefit of it supposedly is that it’s only 8k compared to a megabyte or so that would be added if you used the native C# class, System.XML. I used the C# port by chirhotec in this post. I had to make a small change, commenting out the “string nodeContents” line because the variable wasn’t used.

Where do we start???

  • Load some XML!
So this is the first thing that got me stuck! My main problems getting started with Unity was figuring out how to go about accessing files or instantiating objects. So the first time I got this working, I screwed up…
1
2
3
// DON'T USE Resources.LoadAssetAtPath() !!!

LevelXMLFile = (TextAsset) Resources.LoadAssetAtPath("Assets/PathToFile/StageData.xml", typeof(TextAsset));
Resources.LoadAssetAtPath() only works in the editor. I found this out the hard way when my stages weren’t working when testing on my iPad and Android Tablet. Fortunately the fix was easy…
First you have to move your XML file into a “Resources” folder within the root of your “Assets” folder. Using the resources class, you can grab a reference to any file in that folder. Like so!
1
2
3
// DO IT THIS WAY INSTEAD!!!

LevelXMLFile = (TextAsset) Resources.Load("StageData", typeof(TextAsset));

Now that you have your reference to your XML, it’s time to parse it! To get at all that gooood data.

So…. What next???

  • Parse some XML!

So for my needs, I needed to find a way to loop through each map node, grab the string, and parse out the individual numbers to build a stage. I learned a technique like this working with building tile-based maps.

Here’s an example of how to get to this data using the Lightweight XML parser

1
2
3
4
5
6
7
8
9
10
11
// parse the XML file

public XMLParser parser = new XMLParser();

public XMLNode LevelXML = parser.Parse(LevelXMLFile.text);

// grab the content of one row, shove it in a string array!

public string currentRowString = LevelXML.GetValue("data>0>stage>0>map>0>_text");

public string[] currentRow = currentRowString.Split(',');

Now that’s great! But that’s not very useful. I may have hundreds of rows, so I need to find a way to loop through them.

1
2
3
4
5
6
7
8
9
10
11
12
// find out how many stages there are

public int stageCount = LevelXML.GetNodeList("data>0>stage").Count;

// find out how many map nodes there are in the XML for the first stage
// (hint: I count three!)

public int currentStage = 1;

string _stage = (currentStage - 1).ToString(); // subtracting one, because the XML node always starts at zero! Converting it to a string so I can pass it into my GetNodeList function...

currentMapLength = LevelXML.GetNodeList("data>0>stage>" + _stage + ">map").Count; // checks how many map nodes are within the first stage node

For clarification, what this is basically doing is…

1
// stage 1's map length would be 3, 3 xml nodes.currentMapLength = LevelXML.GetNodeList("data>0>stage>0>map").Count;

while…

1
// stage 2's map length would be 5, 5 xml nodes.currentMapLength = LevelXML.GetNodeList("data>0>stage>1>map").Count;

Now we can loop through these elements…

1
2
3
for (int i = 0; i < currentMapLength; i++) { // get an array of the current row currentRow = LevelXML.GetValue("data>0>stage>" + _stage + ">map>" + i + ">_text").Split(',');

}

So for stage 1, this would loop for 3 iterations.

  1. 1, 2, 3, A, B, C
  2. 4, 5, 6, 7, 8, 9
  3. 2, 1, 3, 5, 6, 2

And by using split() on this text string, it separates each character and places it into an array. In this case, we’re using “,” as the split delimiter. From there we can loop through each individual element…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
...
currentRow = LevelXML.GetValue("data>0>stage>" + _stage + ">map>" + i + ">_text").Split(',');

for (int j = 0; j < currentRow.Length; j++) {

// get an array of the current row

string currentElement = currentRow[j];

// trace out element to Debug window!

Debug.Log("element #" + j + " = " + currentElement);

}
...

So this is a quick and dirty example of how I got it to work. If you need me to clarify something, comment and I’ll see what I can do!

I’ve been a Unity enthusiast for a years but it’s taken some focus to really get down and dirty with it and figure out how to replicate all of the things I’m familiar with in Flash. I’ve been tackling issues with texturing, 2D sprite animation, UI and so on. Looking forward to sharing my learnings!

Peace!

-Bryson

——–
By the way, for code styling, I’m using the CodeColorer Wordpress plugin. Super nifty!

About the author:
Bryson Whiteman (http://www.sonofbryce.com)
Bryson is the guy behind all of the Sokay creations. Heading artwork and development, he's determined to make sure each game has a "distinctively Sokay" quality to them. He's always looking forward for a chance to experiment with new technologies to explore exciting ways to achieve fun.