Let’s discover some Unity tricks to scale images nicely without stretching… and without multiplying the number of assets!
This article is also available on Medium.
In a recent article, I discussed how we can extend our Unity editor and its interface to make our lives easier as developers or designers – but, of course, another key thing when making games is designing interfaces for the players!
Unity, like all major game engines, has really neat tools to create user interfaces quickly and easily. In fact, there are now three UI systems available in the framework: the UI Toolkit, the Unity (Canvas-based) UI, the IMGUI.
Despite having some subtleties in terms of optimisation, the Canvas-based UI is usually the best choice for designing slick and responsive UIs. But to make the most out of your UI components, and in particular your images, there are some options you can play around with…
So, today, let’s see how you can tweak the “Image Type” of your UI images to re-use your sprites in a more clever way! 🙂
A quick note on the Unity UI and images
This UI system provides you with lots of built-in components to create texts, buttons, toggles… and of course images! But when you use this technique, you usually don’t import your images as textures anymore: instead, you use sprites.
To change the image asset type, just choose the right “Texture Type” at the top of the Inspector:
Those sprites can be configured with quite a lot of parameters, but the default ones are usually pretty okay. To make sure you don’t consume too much memory, however, you can reduce the max size of the asset if you know it is not going to be added to your UI with a higher resolution 🙂
Once your asset is ready, you can add it to your UI Canvas by creating a new “Image” object (that automatically gets added an Image component):
As you can see, this component has several options but, among those, there is one called the “Image Type”. This determines how your image is displayed and in particular stretched in the UI if you change the size of the UI element itself…
This property can take four values: “Simple”, “Sliced”, “Tiled” or “Filled”.
We’ll leave the “Filled” Image Type aside in this article, because it is actually quite close to the “Simple” one, except that you have an additional slider to set the “Fill Amount”, and have the rest of the display be clipped out to transparent.
So let’s rather focus on the “Simple”, “Sliced” and “Tiled” types! 🙂
The “Simple” Image Type
In this post, I’ll be working with a non-artistic but (hopefully!) readable image asset that looks like this:
I know, it’s not pretty – but it is divided in several areas that will be important further down the road. More precisely, the image has four yellow squares in each corners, four borders each of a different colour and a pink zone with a visible “F” mark in the middle.
Now, for most of your assets, the Image Type will be set to “Simple” by default. Basically, this mode just copies and pastes the image as-is, without any clever cut and slicing. So you instantly get a basic display of your image:
Nice, right? 🙂
Well – the problem is that if you start and change the dimensions of your UI element to get a different aspect ratio, then the sprite will get stretched in a weird and unpleasant way:
As you can see, the borders of my sprites get really scaled up and our yellow squares aren’t very square anymore. Similarly, my orange and blue borders are a bit too large on the X axis.
Clearly, this Image Type is valid as long as you don’t scale your images too much… but it is limited otherwise! This means that, for example, if you prepare an image like this one which is square and want to use it as a background for a wider panel in your Unity game, it won’t display properly!
An obvious solution would be to also import a second version of your image for the wide panel, with a 2:1 aspect ratio… but then, what if I want something with a 4:3 ratio? Or a 16:9 ratio? Should I just create endless copies of my sprite for all these ratios, just to keep the border size consistent?
The “Sliced” Image Type
Don’t worry: there’s a better solution. The “Sliced” Image Type allows you to adapting one image to multiple sizes without needing multiple assets… but to deal with this specific case, you need to use a little Unity trick: the 9-slicing sprites!
If you try to switch the Image Type to “Sliced” directly, you’ll see that you have a little warning telling you: “This image doesn’t have a border”.
What does that mean?
Well, in order to use a sprite in “Sliced” mode, you first have to cut it down into 9 areas: borders, corners and a center zone. Just like my test image 😉
If we take a look at Unity’s docs, we can analyse their example image and relate it to our own asset:
Here, the image is divided into:
- 4 corners A, C, G and I – that’s like our yellow squares: those get cut and pasted but not stretched
- 4 borders B, D, F and H – that’s like our red, orange, blue and green borders: the B and H borders can be stretched horizontally but not vertically, and the D and F borders can be stretched vertically but not horizontally
- 1 center zone E – that’s like our pink area: it can be stretched horizontally or vertically
Time to apply this technique to our asset, then! To define these zones, you need to go back to the asset Inspector, set its Mesh Type and open the Sprite Editor.
In the most recent versions of Unity, it isn’t built-in anymore and so you’ll first need to install it thanks to the Package Manager:
Once the plugin is added to your project, just change the Mesh Type of the asset to “Full Rect” and then click the Sprite Editor button in the Inspector to open it and edit your asset:
And now, you can just use the editor in the bottom-right corner to set up some options on your sprites, and most notably the size of the borders. Here, my borders are 12 pixels thick:
You’ll see on the left some light green lines that indicate the position of the corners, the borders and the center area on your sprite. Also, when you’re done, don’t forget to apply the settings with the “Apply” button at the top 😉
After configuring our sprite properly, we can now switch to the “Sliced” Image Type and benefit from this to get an unstretched version of the sprite, with nice yellow squares in the corners!
If you want to only keep the borders, you can even uncheck the “Fill Center” option:
The last important thing to note is the “Pixels Per Unit Multiplier” value at the bottom of the Image component. Roughly put, this determines the resolution of your sprite and allows you to “scale down” the corners or borders to your liking:
Thanks to the “Sliced” mode and the 9-slicing sprites, you can easily use one sprite in various contexts, and with different aspect ratios, without having to import a ton of similar assets! 🙂
Just for kicks, here’s an example with a more “pleasant” UI element of a wood-styled panel background – the three panels use the exact same sprite that is set to work with the 9-slicing sprite workflow and gets nicely scaled up without any stretching, no matter the aspect ratio of the container:
The “Tiled” Image Type
Finally, the third Image Type I want to talk about is the “Tiled” type. It’s pretty similar to the “Sliced” mode, but the fill in the center doesn’t get stretched anymore – instead, it gets repeated depending on your “Pixels Per Unit Multiplier”.
For example, with a somewhat low multiplier, I see that my “F” part in the center is repeated twice along the horizontal axis:
Of course, the higher the multiplier, the more repetitions you get 😉
In this quick article, I talked a bit about Unity’s UI systems and how you can set up your images properties to avoid stretching when changing the aspect ratio while maintaining a reasonable amount of assets in your project.
What about you: do you know of other UI tricks for Unity? Do you have any tips on how to make interfaces more efficient and more robust? Feel free to share your ideas in the comments!
And as always, thanks a lot for reading 🙂