Unity UI System - Best Practices
Marble IT
Posted on April 26, 2024
During my development days, I've seen many Unity projects. Sometimes I've made them from scratch, other times I've continued someone else's project.
In either case, when I had other developers in the team, I noticed that a lot of them had trouble with Unity's UI system, whether it's scaling of components, optimizing rendering calls or just plain structuring of game objects.
I noticed that most of them didn't follow any guidelines and just worked based on their feeling of the best practice, which often turned out to be wrong. But that was also true for myself, until the experience taught me better.
What I also found to be the problem is lack of summarized material for my cases, when I didn't want to waste time going through whole documentation. So this is my attempt to summarize key points and solutions that I've acquired over the years.
Disclaimer: note that these are not the official guidelines, and they might not be convenient for every type of project (VR for example) - but these are the ones I've found to be most effective for most projects that will run on screens (mobile, PC, PlayStation, Xbox).
Canvas Component
The only way to start this discussion is to talk about the main UI Component - Canvas. Canvas is the main parent object, that contains all the UI components as children. I will not go into detail about how it works but instead, talk about two key properties when setting it up:
Canvas Render Mode
You can choose among 3 options: Screen Space - Overlay, Screen Space - Camera, or World Space.
The main difference between Screen Space and World Space is that Screen Space will render Canvas in front of the whole game world; basically, it will be fixed on the user's screen in front of everything else. Meanwhile, World Space will be rendered among other objects in the game world, and it can be anywhere, like a regular object that is not a part of UI.
In most cases, your choice will be Screen Space, as the UI components are mostly used for UI indicators inside the game that are always in front of the game world (such as health, inventory, number of lives, timers, etc.).
Canvas Scaler (UI Scale Mode)
This is probably the more important part of the Canvas setup - specifically the UI Scale Mode property. By default, it's set to Constant Pixel Size, which can cause scaling issues upon changing resolutions if left like that. In most cases, UI Scale Mode should be set to Scale With Screen Size, which will give you an option to set default resolution and make objects in UI scale, either with width or height, upon changing the resolution.
Example of Canvas settings for Mobile UI:
One Canvas or Multiple Canvases?
This depends on the use case. Before answering the question, let's talk about draw calls in Unity and re-draws explicitly on Canvas. Let's say that you have one Text component inside canvas which shows the seconds passed since the start of the game. That means that each second, your Text component is going to change. Every time a component changes, the Canvas that contains that Text is completely re-drawn. Now let's say, that you have a few static Image components inside that same Canvas with Text timer. Now, each time a second passes, Canvas is completely redrawn, meaning that not only Text will be redrawn, but all the static Images (which technically don't need that redraw since they didn't change). You can imagine how that issue can scale up when you have multiple components that change inside one canvas - and that's where the second Canvas comes to save the day.
If you have Canvas nested inside a Canvas, when child Canvas is redrawn, the parent Canvas will not be influenced. So the smartest structuring of the game objects would look like this:
This knowledge of Canvas redraw behavior can greatly help when optimizing the game for lower-end devices. Think about it all the time, and it will most certainly improve your game's FPS.
Image Component
Image component is pretty simple by itself. The main challenge is making sure that the image will appear the same on different screens (resolutions). To ensure that behavior will happen, just make sure that Preserve Aspect is ticked. This is how the Image component should look:
The second part of making sure it looks the same on every screen will be explained in the Anchoring section.
Text Component
Like the Image, the Text component is also pretty simple and presents the same challenge - making sure that it looks the same on all screens. This can be ensured by setting a custom Font Size and making sure that Best Fit is unticked! If Best Fit is ticked, the size of the font (text) will vary from screen to screen, as Unity (and Canvas) will automatically change it to what they think is best fit, and you will get inconsistent UI as a result.
Here is an example of how Text component should look like:
The second part of making sure it looks the same on every screen will be explained in the Anchoring section.
Anchoring
Anchors define how your UI component will behave in relation to its parent, and it can be set on each object that has Rect Transform, or in other words, is a part of UI. They look like this by default:
You should never leave them in their default position. By clicking on the Anchor Rectangle in the Rect Transform, you can select predefined anchor positions (top, bottom, left, right, middle, each of the corners, etc.). That menu looks like this:
However, what I suggest to ensure that every object will be placed exactly as you've set it up, regardless of screen resolution is to drag by hand each anchor to the corner of your UI Component. In practice, that would look like this:
This way, however you change the resolution, the object will stay in the same position in relation to its parent.
Conclusion
I hope this basics of UI have covered some of the troubles you are facing and managed to put you on the right way of building the best UI. Happy game creating!
Luka Ćurčić
Posted on April 26, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.