Having a robust process for loading levels is essential. In theory we could save each level as a scene in Unity but it just not going to work once we have a couple of levels. Using serialized text i.e. JSON or XML is very convenient and probably the best thing to do if we also want to tweak the levels in a text editor.
There are a few areas that our XML serializer should address, i.e. default values, rounded values, etc:
Default values for less clutter
It makes sense to assume that the default position and rotation for any item is (0,0) with 0 degrees rotation.
For example let’s say we put a table at position (1,2), rotate it by 45 degrees and put a floor at position (0,0) scale it to (100,200) and do not rotate.
This is how an XML without default values would look like:
<Item prefab=”Table” x=”1” y=”2” rot=”45” scale_x=”1” scale_y=”1” /> <Item prefab=”Floor” x=”0” y=”0” rot=”0” scale_x=”100” scale_y=”200” />
Now let’s cut off unnecessary stuff:
<Item prefab=”Table” x=”1” y=”2” rot=”45” /> <Item prefab=”Floor” scale_x=”100” scale_y=”200” />
It looks heaps better and it’s easier to edit manually. At the same time it’s quite easy to read and write such XML as we just have to introduce a few lines of code as an internal layer between the XML and our GameObjects.
Rounded values for easier manual tweak
If we move an item to position (2.3423534, 1.39371945) we would would like to see rounded values after the serialization into XML, something like this below to ease manual tweaking later on.
<Item prefab=”Table” x=”2.34” y=”1.39” />
Cross checking prefabs in the XML file and the actual assets
Once we have a lot of items it is easy to lose track of the assets that we referenced in the XML file and the actual Assets in Unity. If we have <Item prefab=”Table” /> in our XML but there is no corresponding Table prefab in the /Resources/Prefabs folder then we want to be warned in the development phase.
In this example we will have two levels and will start with level one. We will load a capsule, two cubes and a sphere. This is how the XML looks like:
<?xml version="1.0" encoding="us-ascii"?> <Levels> <Developer StartLevel="1" /> <Level> <Item prefab="BlueCapsule" x="1" y="2" /> <Item prefab="RedCube" x="4" y="1" rot="45" /> <Item prefab="RedCube" y="-2" rot="30" scale_y="3" /> <Item prefab="GreenSphere" x="-4" y="-2" /> </Level> <Level> <Item prefab="BlueCapsule" x="0" /> <Item prefab="BlueCapsule" x="2" scale_y="1.2" /> <Item prefab="BlueCapsule" x="4" scale_y="1.4" /> <Item prefab="BlueCapsule" x="6" scale_y="1.6" /> </Level> </Levels>
Let’s do it in practice
Download the working project (under 100 kB) with git or zip, they are both the same:
git clone https://github.com/TeamBrookvale/UnityXmlLevels.git
After downloading, follow the steps below:
- Open MainScene. You find it at Project pane -> Assets -> LOADTHIS_SCENE -> MainScene
- Click Window -> “Xml Level Editor”
- Delete all loaded XML files: Click on “Delete” button in the Xml Level Editor pane
- Import again: Click on “Import Levels.xml” button in the Xml Level Editor pane
- Create some prefabs and export them to XML:
- Click on the “Export XmlItemsToExport” in the Xml Level Editor pane so an XmlItemsToExport GameObject is created in the Hierarchy pane
- Open the Assets/Resources/Prefabs folder in the project pane
- Drag and drop a few prefabs (e.g. BlueCapsule) on XmlItemsToExport in the Hierarchy pane and move them to random positions
- Once it’s done click again on “Export XmlItemsToExport”
- Now there should be an XmlItemsToExport.xml file in the Resources folder. It should contain the child items of XmlItemsToExport GameObject. You can copy and paste the items back into the Levels.xml file. The contents of the Levels.xml file is loaded upon hitting play or clicking on “Import Levels.xml” button on the Xml Level Editor pane.
- Play around with the Cross Checker in the Xml Level Editor pane. Just add a few dummy items to your Levels.xml e.g. <Item prefab=”NotExisting” />. Click on and the “Cross Check” button in the Xml Level Editor pane and you will be warned in the Console about the missing NotExisting prefab.
That’s it. Have a look at the main files below to understand what’s happening under the hood:
|Levels.xml||All levels in XML format|
|DeserializedLevels.cs||C# class representation of the XML structure|
|DeserializedLevelsLoader.cs||Generates items from Levels.xml|
|DeserializedLevelsSaver.cs||Saves to XmlItemsToExport.xml|
|DeserializedLevelsCrossChecker.cs||Cross checks /Resources/Prefabs and Levels.xml|
|XmlIO.cs||Handles XML file operations|
|XmlLevelEditor.cs||Buttons and labels for the Xml Level Editor pane|
Good luck and feel free to share thoughts or ask questions.