Tutorial: Loading and parsing external XML and JSON files with Unity

来源:互联网 发布:新奇的礼物 知乎 编辑:程序博客网 时间:2024/05/17 03:16

原文:http://blog.paultondeur.com/2010/03/23/tutorial-loading-and-parsing-external-xml-and-json-files-with-unity-part-1-xml/

Tutorial: Loading and parsing external XML and JSON files with Unity – Part 1: XML




As being a Flash Developer for many years, I’m very used to just quickly loading and parsing an external XML file. Although this is possible with Unity, I found out there’s very limited information about this subject available in a Unity context. While investigating this subject a while ago, I also decided to look into the JSON format as a data container, to see which works best for me. Naturally I’d prefer to use XML over JSON, but it turns out that both comes with their cons and pros, which makes it hard to say which works best.
In this two part tutorial I’ll show how you could load an XML or JSON file into Unity and parse it’s information. Both the XML file and JSON file are containers for the same information, which makes it easier to compare the differences between the two.

XML
The XML file I’ve created contains a couple of books. In order to cover different ways to work with XML, it contains a variety of data, like attributes, regular nodes and childnodes, integers, strings and CDATA blocks.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?xmlversion="1.0"?>
<books>
  <bookid="1">
    <title>Papervision3D Essentials</title>
    <image>http://paultondeur.com/files/2010/UnityExternalJSONXML/Papervision3DEssentials.jpg</image>
    <authors>
      <authorid="1">Paul Tondeur</author>
      <authorid="2">Jeff Winder</author>
    </authors>
    <description>
      <![CDATA[<p>Create interactive <b>Papervision3D</b> applications with stunning effects and powerful animations</p>]]>
    </description>
  </book>
  <bookid="2">
    <title>Unity Game Development Essentials</title>
    <image>http://paultondeur.com/files/2010/UnityExternalJSONXML/UnityGameDevelopmentEssentials.jpg</image>
    <authors>
      <authorid="3">Will Goldstone</author>
    </authors>
    <description>
      <![CDATA[<p>Build fully functional, professional 3D games with realistic environments, sound, <i>dynamic effects</i>, and more!</p>]]>
    </description>
  </book>
</books>

This file can also be found on: http://paultondeur.com/files/2010/UnityExternalJSONXML/books.xml and will be loaded later on in this tutorial.

XML is not new to C#. In fact, it’s quite integrated within the language. When you create a new application in Visual Studio, you have access to the System.Xml namespace by default. Within this namespace, lots of classes can be found for creating, reading and modifying XML documents. Accessing these classes in Unity however, doesn’t work out of the box. This is because this namespace isn’t available within Unity. The solution for this is relatively simple; We just need to reference the System.Xml dll in Unity. As Unity is build upon the Mono Framework, this file is provided with your local Unity install. You can find these files at the following locations, depending on the machine you’re running on:

  • MAC: Go to /Applications/Unity/ and right-click on Unity.app -> Show Package Contents. Then browse to “Contents/Frameworks/Mono.framework/”. In this folder you’ll find lot’s of dll files. In this case, just copy System.Xml.dll
  • Windows: Go to C:\Program Files\Unity\Editor\Data\Frameworks\Mono.framework and copy System.Xml.dll from here.

The next thing to do is paste the dll into your assets folder of a Unity project. Next time you compile this project, the System.Xml namespace is available to you from within the Unity player.

To load any external content from a webserver with Unity, we can use the WWW class. (can be compared to a URLRequest in Flash).

1
WWW www = newWWW("http://paultondeur.com/files/2010/UnityExternalJSONXML/books.xml");

Once the data is loaded we can instantiate a new XML document and load the XML by the data that has returned from the www class request.

1
2
XmlDocument xmlDoc = newXmlDocument();
xmlDoc.LoadXml(www.data);

Instead of using E4X (as in Flash) to select childnodes inside the XML document, we have to make use of an XPath expression. In our case we want to select all books, which are nested inside the books element. Selecting nodes returns an XmlNodeList, which will be used to loop through all results. Take a look at how to select all book nodes and loop through them:

1
2
3
4
foreach(XmlNode node inxmlDoc.SelectNodes("books/book") )
{
  .....
}

Inside the loop we have access to the value “node“, which contains information of the selected book. Let’s say we want to access the title node value of the book and show it on the screen:

1
Debug.Log(node.SelectSingleNode("title").InnerText);

Accessing the description (which contains a CDATA block) is no different from selecting the title node:

1
Debug.Log(node.SelectSingleNode("description").InnerText);

Selecting an attribute of a node works of course a bit different. When we want to access the book id attribute we do this as follows:

1
Debug.Log(node.Attributes.GetNamedItem("id").Value);

All values in an XML are of a String type by default. In this case the id attribute is clearly of an integer type. Although it wouldn’t make any sense in this case, casting it to an int can be achieved by using the Convert utils class:

1
Debug.Log(Convert.ToInt16(node.Attributes.GetNamedItem("id").Value));

Inside a book node, we can find an authors node, which contains nested author nodes inside. In order to loop through these, we can again use an XPath expression, only this time on the current selected node.

1
2
3
4
foreach(XmlNode author innode.SelectNodes("authors/author"))
{
  Debug.Log(author.InnerText);
}

Around this concept of loading and parsing an XML file I’ve created a very small Unity application, which shows the two book covers on screen and calls a Debug.Log() on the author name on click on the book. The complete code can be found in the download at the bottom of this article. But the class that handles loading and parsing the XML looks as follows:

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
usingUnityEngine;
usingSystem.Collections;
usingSystem.Xml;
usingSystem;
 
publicclass LoadXML : MonoBehaviour
{
  IEnumerator Start()
  {
    //Load XML data from a URL
    stringurl = "http://paultondeur.com/files/2010/UnityExternalJSONXML/books.xml";
    WWW www = newWWW(url);
 
    //Load the data and yield (wait) till it's ready before we continue executing the rest of this method.
    yieldreturn www;
    if(www.error == null)
    {
      //Sucessfully loaded the XML
      Debug.Log("Loaded following XML " + www.data);
 
      //Create a new XML document out of the loaded data
      XmlDocument xmlDoc = newXmlDocument();
      xmlDoc.LoadXml(www.data);
 
      //Point to the book nodes and process them
      ProcessBooks(xmlDoc.SelectNodes("books/book"));
    }
    else
    {
      Debug.Log("ERROR: " + www.error);
    }
 
  }
 
  //Converts an XmlNodeList into Book objects and shows a book out of it on the screen
  privatevoid ProcessBooks(XmlNodeList nodes)
  {
    Book book;
 
    foreach(XmlNode node innodes)
    {
      book = newBook();
      book.id = Convert.ToInt16(node.Attributes.GetNamedItem("id").Value);
      book.title = node.SelectSingleNode("title").InnerText;
      book.image = node.SelectSingleNode("image").InnerText;
      book.description = node.SelectSingleNode("description").InnerText;
      book.authors = newArrayList();
 
      //Loop the authors
      foreach(XmlNode author innode.SelectNodes("authors/author"))
      {
        book.authors.Add(author.InnerText);
      }
 
      LoadBook(book);
    }
  }
 
  //Finds book object in application and send the Book as parameter.
  //Currently only works with two books
  privatevoid LoadBook(Book book)
  {
    GameObject bookGameObject = GameObject.Find("Book"+ book.id.ToString());
    bookGameObject.SendMessage("LoadBook", book);
  }
}

With this example you should be able to load and parse your own XML files. Before doing this, I need to point you to the fact that using the System.Xml dll results in quite a large footprint to your application. In my tests it turned out that it was about an 850kb difference between having an empty Unity application and an application that is using the System.Xml dll.

In the next part of this tutorial I’ll demonstrate how you could achieve the same results with a JSON file as data container.

  • Download the source files for this complete tutorial (part1 and part2) here.
  • A working demonstration of this example with XML can be found here.
  • Continue reading this tutorial in part 2 about loading and parsing a JSON file.






Tutorial: Loading and parsing external XML and JSON files with Unity – Part 2: JSON

原文:http://blog.paultondeur.com/2010/03/23/tutorial-loading-and-parsing-external-xml-and-json-files-with-unity-part-2-json/






In this part of the tutorial we’ll have a look at how to load the some book information in the JSON format into Unity. For good comparison between JSON and XML, this file will describe the same books and uses roughly the same structure. Take a look at how that looks:

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
26
27
28
29
{
  "book":[
    {
      "id":"1",
      "title":"Papervision3D Essentials",
      "image":"http:\/\/paultondeur.com\/files\/2010\/UnityExternalJSONXML\/Papervision3DEssentials.jpg",
      "authors":
      {
        "author":[
          {"id":"1","name":"Paul Tondeur"},
          {"id":"2","name":"Jeff Winder"}
        ]
      },
      "description":"<p>Create interactive <b>Papervision3D<\/b> applications with stunning effects and powerful animations<\/p>"
    },
    {
      "id":"2",
      "title":"Unity Game Development Essentials",
      "image":"http:\/\/paultondeur.com\/files\/2010\/UnityExternalJSONXML\/UnityGameDevelopmentEssentials.jpg",
      "authors":
      {
        "author":[
          {"id":"3","name":"Will Goldstone"}
        ]
      },
      "description":"<p>Build fully functional, professional 3D games with realistic environments, sound, <i>dynamic effects<\/i>, and more!<\/p>"
    }
  ]
}

This file can also be found on http://paultondeur.com/files/2010/UnityExternalJSONXML/books.json and will be used later on in this tutorial.

JSON isn’t as integrated in C# development as XML is. Furtunatly the JSON documentation website lists external libraries that are available for a variety of languages. Including a couple C# projects. After having a glance at all, I found out that I liked LitJSON the most. It’s usage is quite straight forward. The source of this project can be found on found on SVN. After checking this project out from SVN, you’ll end up with a couple of classes and make files. From these files, a dll should be created for use in Unity. This might sound a bit frightening when you’re new to C Sharp development. Therefore I’ve already created this dll for you (also included in the download at the end of this article). You just need to copy this into the asset folder of your Unity project and from then on you’ll have access to all classes inside of this dll. In order to use them in your scripts, you need to set the using directive on top of your class to:

1
usingUnityEngine;

Just like with XML, we can load the JSON file by using the WWW class.

1
WWW www = newWWW("http://paultondeur.com/files/2010/UnityExternalJSONXML/books.json");

Once the data is loaded from the provided URL, we need to convert the loaded string into an object of the JsonData type. We can use a static method of the JsonMapper class to achieve this:

1
JsonData jsonBooks = JsonMapper.ToObject(jsonString);

Now we have the string converted into an object, we can easily access the objects that have been defined in the JSON file. So let’s say we want access the book object and show how many books are nested:

1
Debug.Log(jsonBooks["book"].Count);

That looks easy, right? jsonBooks["book"] holds an array of books, so in order to loop through all books, we can use a simple for loop:

1
2
3
4
for(inti = 0; i<jsonBooks["book"].Count; i++)
{
  ......
}

In this example, it will loop through the two books. While looping through them, we can print the book title on the screen:

1
Debug.Log(jsonBooks["book"][i]["title"].ToString());

Notice the ToString() method call at the end of the selected object. This will convert the object into a string. C# is more strict with this as compared to ActionScript, so never forget to call this to prevent errors.

Now let’s say you want to access the book ID and treat it as in integer. You first need to convert the object to a string and then convert it to an integer.

1
Debug.Log(Convert.ToInt16(jsonBooks["book"][i]["id"].ToString()));

Nested inside an book object are the authors. Looping through them is quite easy, as we can you access these nested elements. Look at how to loop through the authors and print their names on the screen:

1
2
3
4
for(intj = 0; j<jsonBooks["book"][i]["authors"]["author"].Count; j++)
{
  Debug.Log(jsonBooks["book"][i]["authors"]["author"][j]["name"].ToString());
}

I’ve recreated the same example as used in part 1 of this tutorial, only this time with a JSON file as the data source. The complete source can be found in the download, however have a look at the following code to see how LitJSON could be used in production:

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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
usingUnityEngine;
usingLitJson;
usingSystem;
usingSystem.Collections;
 
publicclassLoadJSON : MonoBehaviour
{
  IEnumerator Start()
  {
    //Load JSON data from a URL
    stringurl = "http://paultondeur.com/files/2010/UnityExternalJSONXML/books.json";
    WWW www = newWWW(url);
 
    //Load the data and yield (wait) till it's ready before we continue executing the rest of this method.
    yieldreturnwww;
    if(www.error == null)
    {
      //Sucessfully loaded the JSON string
      Debug.Log("Loaded following JSON string" + www.data);
 
      //Process books found in JSON file
      ProcessBooks(www.data);
    }
    else
    {
      Debug.Log("ERROR: " + www.error);
    }
 
  }
 
  //Converts a JSON string into Book objects and shows a book out of it on the screen
  privatevoidProcessBooks(stringjsonString)
  {
    JsonData jsonBooks = JsonMapper.ToObject(jsonString);
    Book book;
 
    for(inti = 0; i<jsonBooks["book"].Count; i++)
    {
      book = newBook();
      book.id = Convert.ToInt16(jsonBooks["book"][i]["id"].ToString());
      book.title = jsonBooks["book"][i]["title"].ToString();
      book.image = jsonBooks["book"][i]["image"].ToString();
      book.description = jsonBooks["book"][i]["description"].ToString();
      book.authors = newArrayList();
 
      for(intj = 0; j<jsonBooks["book"][i]["authors"]["author"].Count; j++)
      {
        book.authors.Add(jsonBooks["book"][i]["authors"]["author"][j]["name"].ToString());
      }
 
      LoadBook(book);
    }
  }
 
  //Finds book object in application and send the Book as parameter.
  //Currently only works with two books
  privatevoidLoadBook(Book book)
  {
    GameObject bookGameObject = GameObject.Find("Book"+ book.id.ToString());
    bookGameObject.SendMessage("LoadBook", book);
  }
 
}

This gives an idea how to handle JSON files in Unity. Just like with XML this comes with a disadvantage in terms of filesize. It’s size footprint to the Unity file is about equal to XML: +/- 850kb. A live example of this can be viewed here.

Conclusion
I think it’s quite hard to say which file format is better. Both XML and JSON add about the same amount of kilobytes to the Unity file. I’ve not tested which of these is more efficient performance wise. It might be worth checking that out before you’ll be working with large amounts of data. In case that doesn’t matter, I think it’s just a matter of personal taste. I think I kind of prefer to use JSON, as this reminds me of handling XML files with ActionScript in the AS2 days.
But give it a try yourself and see what works best for you.

Downloads / Examples

  • Download XML and JSON example files
  • Download LitJSON dll file
  • View XML Example
  • View JSON Example
  • Go to part 1 of this tutorial
0 0
原创粉丝点击