How to Make a Modular UI in Unity
It’s been an interesting week that I have been playing out with UI tools for Unity. If you haven’t read my other post about modularization, I strongly recommend to read it. Achieving a more maintainable and modular UI is possible with Unity, however, it is not by default. I will try to explain why and how in the rest of the post.
What is a Modular UI?
When I am talking about modularity, I mean dividing a structure into reusable, controllable pieces. UI structures can be split into pieces as well as the code structure. For example, let’s imagine that you are given a UI task. You should create two pop-up windows. One window should contain a text and two buttons while the other window should contain a text and one button. As you can also come up with, there are many ways to create these windows.
The first is the naive way. You can build two windows using the building blocks given to you by Unity. You can see an illustration below.
The second way can be more modular. It seems that we can divide this popup as a Panel and a Content. We can reuse the same panel and inject different contents into it. This way, we would never need to create a new panel. Here is an illustration below.
Maybe this is not so in-depth, but the idea is reusing some parts so we would never have to recreate it. Having this modular way with Unity’s current UI system is not possible. I mean you can have a workaround with nested prefabs, but I personally don’t like that way due to lack of trackability in the source control system.
Unity and UI
In the current state, Unity has lots of visual and interactive components for UI. Unity UI components are much like building blocks. We can practically wrap these blocks using layouts and build a complex and responsive UI.
This is usually enough. If you are making a casual game, most probably you wouldn’t need any complex UI. You would use the same UI structures by turning into prefabs. However, if you are going a little bit big than that, Unity fails providing a modular UI framework. The reusability of a created UI structure mostly follows a copy-paste-edit triangle.
Unfortunately using the prefabs are the only way to make the UI a bit more modular in Unity. I actually don’t like this, because this is not really traceable as you can see from the picture above. I can’t see what has changed on the GitHub.
A New UI System from Unity: UIElements
This feature is something I have been waiting for. Finally, it is available as a preview package so we can play with it. The UIElements feature is actually quite promising. It provides a way to make the UI modular using UXML and USS files.
Briefly, we will be able to create the UI structures withing UXML files, then we will style the structures using USS files. We can reuse UXML files inside other UXML files and we can have default styling for the whole project. This is really amazing because UI will be readable, traceable over source control and more reliable.
As you see in the picture, I was able to create a generic panel in minutes. I can put whatever I want into the #content node. In this example, I’ve put TextWithButtonV.uxml. This panel will be reusable, even for the other games I create. So you get the idea why modular UI can be a good investment in the long term.
There is only UI Builder for now, but since there is no PanelRenderer (expected in the 2020.1 version) for the runtime GUI, you can’t use what you have created with the UI Builder. Unfortunately, according to Unity’s road plan, we will need to wait for the 2020.3 version for this feature to be production-ready. Until then, we need a backup plan. You may continue to what you have been doing, or I have a great asset for you to make your UI more modular.
An XML driven UI Framework: XmlLayout
XmlLayout allows you to create UI using XML files and these files are reusable in the other XML files.
Does it sound familiar?
Yes! This is a very close approximation of Unity’s new UI system UIElement. Unfortunately, XmlLayout doesn’t provide a visual UI builder, but this is not a huge miss. Even though it takes some time to learn it, it is quite fun to create stuff with it. Especially, being able to set percentages for defining the width of the UI is very nice. Every XML component comes with its controller in C#, so you can manipulate the UI in case it is needed. I think that’s a paradise for game UI development.
Here is the developer’s definition of the framework;
XmlLayout is a framework for Unity UI which allows you to develop professional, fully functional user interfaces and UI elements using XML.Digital Legacy Games
As it is described, it gives you a professional view on creating the UI. You start to differentiate parts like views and controllers. It has lots of inspiration from web-based frameworks. I work with Apache Wicket with Java and it has a way to utilizing ‘HTML+JS+CSS’ behaviors. You can have child components and you can manipulate your components using Java. XmlLayout does almost the same duty as Wicket does but with XML files and C#.
Debugging the UI
XmlLayout makes your code easier to debug. How?
As I stated above, every XmlLayout component has a controller in c#. So if you could keep your components as atomic as possible and create bigger components from the primitive ones, then you would have the same child-parent relationship with the controllers. Thus, when there is something wrong you would look at the right controller or track the root cause of the problem in a short amount of time.
I guess it is quite understandable how XMLLayout components are reusable. You can reuse your atomic components inside other components.
For example, I have created an advanced progress bar with XmlLayout and I use it as an energy bar. Since I need two energy bars, I can reuse it as a blue energy bar and red energy bar. I don’t have to drag and drop two prefabs to the scene. I just give two references to my layout from the energy bar XML file. The rest is managed by the asset itself.
You can even have a base XML file in which you define the common rules between components so you won’t have to rewrite those. I am having a theme and color-related styles. So, I keep the coherence between the UI elements.
I love the stuff that I can track from the source control tool. I see the changes and history for my custom XML components. The traditional way of Unity is impossible to track. If someone is changing or editing the prefabs and creates a bug, good luck with that.
When it comes to readability, well it is UI in a readable form. However, it takes some time to adapt to its syntax rules. If you worked with CSS before, it won’t take much time. The rules are quite similar to CSS rules or logically inferable.
As the last thing, when you actually understand this new way of creating the UI, your UI code would be much more reliable since this tool will always regenerate the same component for every time and you won’t have compatibility issues. It is also great that the tool gets regular updates and it adapts itself to the newer versions of Unity.
An Example of a Modular UI
I have created a popup window with a text and button in minutes. First, let’s take a look a the XML below.
<XmlLayout xmlns="XmlLayout" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="XmlLayout UI/XmlLayout/Configuration/XmlLayout.xsd"> <Defaults> <Panel class="generic-panel" width="50%" height="50%" image="panel_bg" type="Sliced"/> <Panel class="panel-content" rectAlignment="MiddleCenter" width="98%" height="70%" image="panel_content" type="Sliced"/> </Defaults> <Panel id="panel" class="generic-panel"> <Panel class="panel-content"> <ChildXmlLayout viewPath="TextWithButtonV" /> </Panel> </Panel> </XmlLayout>
In the first part, I have defined Defaults, which is simply the style definition for the components. This is good separation because later we can modify these values independently from the structure. You don’t have to define this in this way, but I strongly recommend you to do so.
The content setting for this panel is done inside the ChildXmlLayout tags. I refer to another XML file which is TextWithButtonV. This way I can modify the content of panel without touching its XML, or I can reuse TextWithButtonV wherever I wish for.
It may look like a lot of work at the start, but once you start to reuse old components you have created, it is more enjoyable. XmlLayout lets you extend the tool, so you can create your own components. For example, I can create the Panel above as CustomPanel and put the child XML as an XML property. Then I can reuse the panel without any copy-paste. I guess, you get it and are able to see what you can do with this tool.
Advantages over Unity UI
- Easy to track with source control tools
- It gives a better MVC feeling
- Readable UI elements
- Child-Parent relationships between components
- Once you have learned, it provides a faster way to create UI
- It simply generates the UnityGUI, so you can fit this tool even if you are working with prefabs.
- Takes more time to learn it
- Documentation can be frustrating sometimes.
- Not all of the UnityGUI features are reachable from the XML, so sometimes you need to do what you need in the controller which is not so neat.
Conclusion: Modular UI
There is a big question to ask before taking any action. What will happen to XmlLayout once Unity UIElements is production-ready? The answer is that Unity will keep supporting the old UI system. It means that XmlLayout will be still working for a long time. Therefore, you will have some good time to migrate from XmlLayout to UIElements. Since they are both XML based, it won’t be so hard to migrate.
In my opinion, creating a modular UI has a great deal of value. Once you have your UI element as flat XML definitions, it would be easier to modify and maintain them. You can even create an independent UI module in which you can reuse it in the other games.
Even though it takes some time to learn it, think this as an investment. If you plan to stay as a game developer for a while, then it is worth to have this tool within your indispensables.
Stay tuned! and please comment about the tutorials you wish for!