In this tutorial I will be showing you some of the best practices for user interface (UI) design. This guide is designed for the people who are new to the topic, and are wanting to start making UIs or improve their existing skills.
This tutorial will steal a lot of ideas from general design - as that’s what essentially it is.
I would just like to say that while I may refer to something as being incorrect, there really is no improper/mistaken/bad way to design things - usually something ‘improper’ just doesn’t fit our particular tastes. Feel free to mess around with design.
Please excuse my inconsistent screenshot sizes
Size & Position
ROBLOX GUI objects have all of their measurement done by a value type called
UDim2, which stands for Universal Dimension 2 (as in it is comprised of 2
UDim value consists of two numbers:
Scale is a measurement based on the screen size - the number 1 would represent the entire size of the screen, and 0 would represent nothing. This also has compatibility for negatives and numbers larger/smaller than 1/-1.
Offset is simply a measurement of pixels.
A Frame being the horizontal size of its parent - minus 40 pixels (an example of margins, which will be discussed later) - and having a height of 30 pixels.
All objects that have text also have a property called
TextScaled which is a bool of whether the text will resize itself to fit the size of the object is being applied to. It is useful if you’re being lazy about the size of UI elements.
A common mistake is to use
TextScaled) to give measurements to everything. Unless you are doing it ‘right’, you’ll just end up with varying element sizes.
Note: The third button is an example of text wrapping. For things like buttons, you would usually want to disable this. This will be explained more in the text section.
Scale - or when, in fact, using anything at all - you will usually design to look good in a specific screen size - usually the size you have it set to in studio. This often leads to elements not looking right when playing outside of studio.
The following example is of how using
Scale can alter the actual size of the elements.
This is not a particularly great example - the difference here is kind of subtle. You can see the difference mainly with the cursor (an element which stays the same size across diverse screen sizes) - it is showing that the in-studio elements are actually quite smaller than the elements from the full 1920x1080 game.
This often leads to UIs designed with
Scale feeling clunky and too large and invasive on the main screen space.
I personally prefer to design the majority of my UIs using
Offset - why?
Offset is more consistent - the actual size of the element does not change whatsoever across platforms. This doesn’t work so well in terms of mobile screens and consoles, and does require individual designs for each platform but you should be doing that anyway to provide optimal experience for everyone.
I only use
Scale when I am:
- Designing something that will be changing sizes (See this video for an example - note that the text was at a fixed size - https://www.youtube.com/watch?v=F46B3is1wD4).
- Designing a BillboardGui (using
Scalefor the size property in the
BillboardGuiobject makes it resize automatically based on distance instead of staying a fixed size on your screen).
- Designing something to consistently be
x%of a parent object when the parent object’s size can vary and the calculations can be uniform and do not need to be changed (e.g. a health bar; http://prntscr.com/gnrglf).
Under most other circumstances
Offset should be used simply because everyone using it will be getting roughly the same, (hopefully) clean experience.
All GUI objects also have a property called
AnchorPoint. This property is a simple
Vector2 where each of its values range from 0 to 1 - similar to the
Scale value in a
UDim. The anchor point defines where the position will be applied to.
Currently, this frame has an
The frame is being positioned from the top left corner, so that anchor point will be where the frame’s Position property is.
Alternately, you could set the
1,1, so it will be positioned from the opposite side:
Or, you could even change it to
0.5,0.5 so the object would be positioned from its center like parts are:
AnchorPoint main function is make to positioning GUIs easier and let you use less brainpower trying to calculate the position. This allows you to simply position an object at the bottom of the screen using a
1 - as long as the
Y property of the
AnchorPoint property is set to
1, the object will also be fully visible.
AnchorPoint is a really useful, so you should definitely not rule it out of the question when designing UIs.
There’s a property in every GUI object called
ZIndex that defines it’s ‘z’ position. This defines whether an object is in front of another (meaning that even the 2D side of ROBLOX isn’t really 2D lol).
The object with the highest
ZIndex is in front of objects with a lower
You may or may not have noticed that some colors at their fullest brightness still appear to be darker than other colors - for example, red or blue - and some colors are still bright.
The opposite of this is also true - the brighter colors are harder to see in front of a white background.
You will want to consider what color your text is - if you really want to use a specific color, like blue, consider adding some white to it so it becomes easier to read with a black background, and vice versa.
All text objects have two properties:
TextStrokeColor3 can be anything you want, as long as it has contrast with you its
If there isn’t contrast:
- The text starts to lose its defining shape and clarity.
- It’s hard to read.
- And just doesn’t look all that great.
Alternatively, it could look like this:
- The text is clear and easy to read.
- It looks pretty nice
- And the text can now be seen in front of any background as the stroke separates it from the background.
Stroke is very useful for white text as a transparency of 0.8 allows for that barely visible amount of shadow that distinguishes it from the background.
An important thing to remember for text is what is behind it.
A cluttered background behind text can hide letters in a sea of varying color. The text becomes just another meaningless pattern.
Usually you’d want to keep what is behind the text so people can easily read the complex symbols that make up the alphabet:
You can see that the text with the blurred background is easier to see - this is because blurring essentially simplifies an image. It becomes less cluttered, and sharp shapes are now contrasting with smooth, fading shapes.
The text with the plain background is even easier to see - there is nothing behind it conflicting with the text.
Text wrapping occurs when text automatically creates a new line when it has reached the edge of its defined maximum area. You see it in almost every word processor.
This is an example of text wrapping:
And this is an example with it:
While it is incredibly useful for long bits of text in say, an essay, it is not practical when using buttons. It makes the text either go out of visibility or the text size will have to change, making an inconsistency. The best solution is to disable wrapping and increase the size of either that single button or every button.
Images are very important as they open up a whole new range of custom shapes. The ROBLOX 2D engine is rather limited in the shapes it can provide, so uploading custom shapes is always helpful!
Often using unique images helps give your game identity and also can work with immersiveness. Making a cartoony game? Use big, round shapes and bold text!
Making a western game? Give all of your UI elements a woodgrain texture!
The size of an image is actually very important.
The first golden rule is to never use an image at size larger than what it is. For example, NEVER use a 20x20 image and scale it up to 100x100.
The second rule (to make your images gold and not silver) is to use your images at exactly the same size as they are. If you have a 20x20 image, use it only at 20x20.
Offset often can come in handy in these situations.
Small | Original
The original image looks more crisp than the image on the left. Unfortunately I’m bad at examples so the scaled-down one kinda looks better on the eye in this example (tell your image maker to use anti-aliasing for stuff like this!).
9-Slicing is a technique used to make images scale without the edges losing quality and shape.
The original size of the image in the following examples is 200. The image on the left is without slicing, the image on the right is.
There are some small differences you might pick up - hint: look at the corners.
So how do you do it?
9-Slicing slices an image up into 9 rectangles - 4 of which (the corners) don’t change the size at all.
The 4 edges don’t change size on only one of the axes, meaning a horizontal edge won’t change it’s Y size.
This leaves a final part - the center. This will make up the majority of your image, and is recommended to be a plain color.
Each image object has a property called
ScaleType. Setting it to
Slice will reveal a new property called
This revealed property is a
Rect2 which two values for each corner of box to be the ‘middle’ part of your image.
These values define the center rectangle - the final outstanding part I talked about just before. The first two values of this
Y0 define the starting point in pixels of the center part based on the original image. The latter two,
Y1 of course define the ending point.
Each of my corners is 10x10 and the original image size is 200x200.
You can find a more in-depth tutorial here: How to use SliceCenter (Roblox's 9-Slice GUI Property)
Often you may want to make a button that you hover over have a special effect or an image be animated. You don’t want to upload lots of images for one simple thing… so that’s where spritesheets come in.
Thanks google images
A spritesheet is made up of different sections all in the same size. It is responsible for holding entire animations in a single image.
So how do you implement this in ROBLOX?
All image objects have two properties:
ImageRectOffset, which are both of the
Rect value type (which is similar to a
To define the size of each different sprite, you set
ImageRectSize. To change which sprite the image is currently ‘viewing’, you use
ImageRectOffset and set it to the location of the sprite (all in pixels of course).
Here’s an example:
My 52x104 spritesheet
Margins (AKA padding) are something that a lot of people miss.
I think margin isn’t the proper word for the topic, I should be using padding shouldn’t it?
The thing with not having a margin is that your design looks… cut off. It doesn’t end naturally, you (should?) say, even though it technically does. Eyes like breathing room - that pretty much sums up the use of margins aesthetically.
This problem is also accentuated by the contrast of there often being a margin on the other side of the text - creating an unsatisfying imbalance.
The answer to this cut-off feeling is to add a few pixels of empty space before the element ends.
Most commonly this problem is found in objects with text, where the
TextYAlignment is set to
Unfortunately, the only real solution to this in terms of text is to create a different object for the text object’s background, as there is no margin system for text objects:
This is one variation of the solution… muuuuch better…
Sometimes margin is not used in a textual context - maybe you just want a frame inside another frame to have a margin (and scale properly if you’re someone like me) so you can see the difference.
There are two options: Do it manually, or use a
To do it manually, you would give it the appropriate size so it fills everything you want it to fill without the margin:
Then, you would subtract
x*2 from the size, and add
x to the position, where
x represents the size of the margin you want (these are all in
Offset, so make sure to use pixels!)
Also, to improve the scalability of your element, you should be using
Scale to get the general size, and
Offset to get the margin.
To use the
UIPadding object you would give it the same parent as the object you would to apply the margin to. You would then set each corresponding
Offset value of all of the
Padding properties to
Here’s an image of the properties of
OtherFrame at that time, to show you how easy this object makes it:
UIPadding will apply to every child of its parent, so if you have other elements in
Frame, it would give them padding too.
Margins are most commonly used in a ROBLOX context to separate an object from the edge of the screen - although in terms of edges, a margin is not necessarily required, as the design can still look quite good without one.
A few final things to follow when designing in general:
Try to have contrast between elements - firstly not having good contrast at all would make things hard to see, and secondly people with poor eyesight would have a much harder time (grey text apocalypse, anyone?)
“Dark” colors like blue, purple and red are hard to see in front of a black background - but we should have already covered that in the text section.
Try to keep your UI from intruding upon the game - if you have sidebar buttons that cover a third of the screen, that’s not a very good use of space if your game is a shooter. This might be appropriate if you are doing something that does not exactly require large viewing space - for example, a city builder. Now even in that context, one third may still be too big for buttons.
The same goes for anything else that can appear on the screen.
Consistency! Your UI should have the same style in all of its elements.
If you’re going to use a free model or buy some scripted GUIs, make sure to edit the appearance of them.
Examples in Action
This is a thread showing a UI I made for a group (it is a good example of using image size properly):
This is a dead game I made:
Global Leaderboard makes me a hypocrite.
And of course a semi-professional example:
New Zealand politics lol http://www.labour.org.nz/
I really like the recent design trend that uses text highlighting.
You can also check out the games on the front page - most of them usually have a pretty nice UI.
Hopefully this was helpful
Good luck designing UIs!
Edit: Silly me didn’t do a proper search for other tutorials on this topic. Cool.