Updated Oct. 27, 2019.
Developing a truly resolution independent user interface is not easy, especially for desktops and laptops. By resolution independence, I mean being able to design the UI once, and have it work at all resolutions, especially the wide range of resolutions on desktop. I’ve read a lot of posts and tutorials online, experimented with various methods, performed a lot of tests, and what I’ve written below is my current understanding of the various methods.
From what I’ve seen, there are 7 general methods, and combinations thereof, which developers use to create a UI for different resolutions. The first 6 use Unity UI (now a package) and Unity’s TextMeshPro package for SDF fonts (works great for resolution independent fonts). Keep in mind that Unity is releasing a runtime version of their new UIElements framework in version 2019.3, which will eventually replace Unity UI once it is feature complete. I don’t plan on testing it much since Unity is planning on it being production-ready in version 2020.3. I’ll list the advantages and disadvantages of the various methods and offer my thoughts on each:
1. Make a non-scaling UI (in Unity, this is a UI with Constant Pixel Size set for the UI Scale Mode of the canvas) with panels anchored to various edges of the screen.
- Can create bitmap images at exactly the size you need, and have them be very crisp and sharp on screen
- Design at the lowest resolution you need to support to make sure no elements overlap, and you should be good.
- Can have very small pixel perfect fonts, if that’s what you need.
- UI doesn’t scale, so the UI will tend to be very small at resolutions like 4K, and will take up a lot of screen space at low resolutions.
- In my experiments, with a generic window panel in the middle of the screen, it will take up most of the screen at 1366×768, and will be a very small panel in the middle of the screen at 4K.
Looking at the Steam Hardware Survey, as of October 2019, there are roughly 5 times more people using a 1366×768 monitor than those using 4K, although this will probably change over the next few years. If we want our games to last and work well as display resolutions increase in the future, we need to account for these sizes and perhaps more.
The above technique, while viable when we only needed to design up to HD (1920×1080), doesn’t seem that practical nowadays with such a huge range of resolutions. If we only need to anchor some elements to the corners of the screen, or there are very limited ranges of resolutions we need to support, then this technique can be useful.
2. Create multiple assets for various resolutions (like SD, HD). For example, larger images for larger resolutions, and smaller images for smaller resolutions. Set text sizes for various resolution ranges.
- This technique also seems to be useful for more limited ranges of resolutions, and allows pixel perfect crisp images and texts.
- Can become a headache to manage all the various assets and sizes of panels. With 4K, we may even need 3 sizes of each asset – SD, HD, and UHD.
- This becomes problematic with complex UIs with lots of elements next to each other. When you swap out assets at different resolutions, the sizes of elements will change, making it difficult to keep things relative to each other.
This technique also tends to be more useful for simple UIs, or things anchored to corners. With complex UIs, this technique quickly becomes unusable unless you use lots of layout groups. If your animations rely on certain sizing, this technique may require a lot of extra work depending on the complexity of the UI.
3. Create a UI Canvas that scales (in Unity, set UI Scale Mode to scale with screen size) using bitmap images.
- You only need to create one version of the UI that will always take up the same proportions of the screen no matter the resolution.
- Let’s say you design all your bitmap images for the largest resolution. For lower resolutions, this might be ok if the images are relatively large, as downsizing usually produces better results than having to upsize. But if screen resolutions larger than what you designed for become popular, then your images will need to be upscaled, losing quality. Also, sometimes the downsizing produces artifacts in the images.
- Thin lines, edges, and text become blurry and unclear at different resolutions, even with pixel perfect enabled. Sometimes artifacts show up, or lines simply disappear as there are not enough pixels to reproduce the item at low resolutions. You may need to play with various settings of the texture importer, like whether to generate mip-maps for the chosen image, whether to use Point vs Bilinear or Trilinear filtering, etc.
No one wants to see a blurry UI, especially one with artifacts.
4. Create a UI Canvas that scales with screen size using vector graphics (SVG).
- Relatively crisp UI at all resolutions, as vector graphics scale beautifully.
- Just like #3, you only need to design the UI at one resolution, and have it scale nicely to all other resolutions.
- There is now an SVG package in Unity’s Package Manager which allows using SVGs in SVG Image components.
- You will need some form of anti-aliasing for the edges, whether MSAA or some form of post processing AA, or shader-based ant-aliasing. On Unity’s forums, I’ve been constantly asking the devs about an alternate form of antialiasing for SVGs, as MSAA does not work for Screen Space Overlay UIs, or in deferred pipelines. They’ve stated that they’re currently working on solutions for this. While certain forms of post processing anti-aliasing work well for SVGs, they also affect the thickness of fonts, which is not desirable.
This would be the best current method of doing resolution independent UIs, if Unity could tackle the SVG AA problem for Overlay UIs. There are 3rd-party SVG assets on the Asset Store that include some form of shader-based anti-aliasing, but that leaves you dependent on those developers unless you know your way around their source code.
5. Use a UI Canvas that scales with screen size with SDF textures
- Crisp edges of UI images at all resolutions.
- Like #3, you only need to design the UI at one resolution, and have it scale nicely to all other resolutions with just one asset per image.
- Minor cost as it requires purchasing an SDF image asset from the Asset Store.
- Fiddling with the settings and some testing to get the best generated SDF texture.
- Unable to have too many colors in a UI icon due to the way SDF works. It does work great for single-colored UI icons.
This is the method I found that gives me the best results. You can use an asset like SDF Toolkit or I2 SmartEdge to generate the SDF texture and use that for the UI images, which scale well at all resolutions with the right settings of the spread factor, softness, etc.
6. Use a UI Canvas that scales with screen size with procedural UI shapes
- This gives resolution independent UI elements, albeit using primitives with various numbers of sides only.
- You don’t have to worry about lots of various UI textures.
- Minor cost, as you usually have to buy these assets from the Asset Store, unless you use the generators from the free UI Extension project, but then you’ll get jagged edges unless you use MSAA, which leads to lower performance and more memory usage.
- Need to find an asset that uses shader-based antialiasing, otherwise you get lots of jaggies.
This is a pretty good alternative to having to create the elements yourself. The one I found that fit my requirements: Procedural UI Image. There are others if you do some searching on the Asset Store.
- Design once and have it work at all resolutions.
- Crisp images and fonts.
- Depending on the system, GPU accelerated.
- Can use a technology you may potentially be familiar with, like WPF for Noesis, or HTML/CSS for Coherent
- Cost… these UI packages can cost quite a lot depending on the licensing. NoesisGUI is free under a certain income limit, which is really cool. Coherent Labs’ offerings seem more suited to huge budgets.
- Need to learn a different UI system, possibly different tools, and all the quirks associated with each. Some of them use different programming languages as mentioned above.
- Slight performance hit of using antialiasing, though these solutions tend to have efficient methods of implementing it.
These systems seem to be what many bigger game studios use and are nice for having there be a separation between the UI and the code behind it. Unity’s upcoming UIElements also takes separation of styling and code into account as well. There will be a bit of a learning curve for these systems, depending on your current knowledge.
Currently, I’ve settled on a mixture of #5 and #6, using SDF image icons, Procedural UI rounded shapes, and TextMeshPro for fonts. I may swap out the SDF images for SVGs depending on how Unity implements their anti-aliasing for Screen Space Overlay canvases.
I hope this post has at least given someone a better idea of the various options for producing a truly resolution independent UI. If you’ve discovered more methods, please let me know in the comments below. Thanks!