Scale friendly UI in Unity

There’s already wide array of great tutorials in Unity for creating an UI for your game ranging from very basic tutorials on how to drag elements such as images and controls such as buttons to your user interface to more advanced stuff like using them in the world space.

The newer UGUI system is very flexible which is great if you know how to use it, but can cause a lot of unnecessary problems and re-work if you don’t. In this tutorial I am hoping to pass on some of the experience I have gathered while working with the system and NGUI for 3 years or so.

Setting up the Canvas

Personally I dislike how the Screen-space overlay setting in the canvas works by using 1:1 pixel to meter scale to define the physical size of the user interface. This makes it ridiculously big in the editor and personally I find it difficult to work with, so I always go for the Screen-space Camera setting which allows me to attach the canvas to a camera object that’s dedicated for displaying the user interface. From there I can manipulate the physical size of the Canvas by adjusting the plane distance.

I also set the culling mask from the attached Camera to only render the UI layer and remove it from the Main Camera so that it doesn’t get rendered twice.

UICamera_and_Canvas

I also set-up the Graphic Raycaster to block only 2D objects in the UI Layer because more often than not the User interface elements are two dimensional. Rect transform values in this case are driven by canvas so they cannot be altered. The child HelloLbl is just a text element that I placed under the canvas.

Canvas Scaler

The canvas scaler attached to the canvas is a handy tool which defines how your user interface behaves on with different resolutions and aspect ratios.

If you’re making a game for desktop computers then I recommend you to use the constant pixel size mainly because displaying images on their intended size just looks better than if they where shrunk or stretched. With players using something as precise as mouse and looking the screen from very short distance smaller user interface is actually preferable with higher resolutions. For those who don’t you can add a setting to the settings window to alter the scale factor to make the elements larger.

For mobile games and maybe console games I would recommend using the Scale with screen-size and using reference resolution that matches the resolution of popular smart-phones or using the standard FullHD (16:9) resolution  1080 × 1920 for portrait and 1920 × 1080 for landscape. Mainly because touch inputs are not as precise as mouse clicks and this could make small buttons and sliders difficult to manipulate on a device that has very high resolution in comparison to it’s screen-size. With home consoles users maybe as far as 3 meters (10 feet) away from the TV which can make small text in your game very difficult to read.

Scale-with screen size also comes with Screen-match mode which is useful for dealing with different aspect ratios.  It defines how the screen-height and screen-width affect the scaling in your game. It’s good to play around with it a bit using the Free-aspect setting in Unity editor and trying different aspect ratios and how it affects your user interface.

There’s really no silver bullet for it as it depends a lot on whether you want to use portrait or landscape or both on mobile and whether you have a lot of elements with anchors using horizontal or vertical stretch.

Creating new UI elements

Usually the best way to start creating a new element is to add a new rect transform to your canvas that can be used to specify the size and position of the element. This can be done by:

  • a) adding a new empty game object to your canvas (select canvas -> right click -> create empty)
  • b) adding new image game object to your canvas and removing the image component.

Like in my previous tutorial on intractable elements I like to keep the parent element as clean as possible from unnecessary components.  Personally I like to separate even the background of the element and just set it to stretch to the size of the parent element.

UI_Element_hierachy

Basic Element here is the Root element and it has 3 children one being the blue background, second being the close button with label “OK” and last being the actual content.

Importance of Anchor and Pivot points

Anchors and Pivot point play a major role in displaying your user interface properly on different resolutions. For example if your element is supposed to be displayed on the left corner of the screen it’s important to set  both it’s pivot and the anchor to the bottom-left corner of the element that way it the element will retain it’s distance from bottom-left corner with different resolutions even when it’s resized.

For floating elements like the one in picture above that you want to display at the center of the screen it’s best to set the pivot and the anchor to center. For Windows, Pop-ups and dialog boxes it’s advisable to avoid using stretched anchors on parent elements like a plague. Stretched anchors tend to cause a lot of unnecessary problems with different resolutions and aspect ratios and it’s generally better option to allow the user to resize the windows themselves rather than try to figure out what they want.

Anchors

One should learn to love anchors in Unity when creating elements for your user interface in unity. The help immensely when you want to position the element relative to center, corner or side of the screen without having to deal with screen-width and screen-height calculations to know where you should position the element on different resolutions. However the best thing about them is how they do not only work under the canvas but other Rect Transforms as well which makes structuring UI elements a lot easier.

Strechable_content

For example here I am using the “4-way stretch” anchor to specify the size of the content with small padding on the top, left and right side of the element. I have also specified the content to give the CloseButton 40 pixels  of space from the bottom.  Now the element could be freely resized as long as it’s at least 50 pixels or so in height.

You could also specify other sections of your element the same way I specified the content. E.g you could use the top-left top-right stretch to specify 40 pixels in height section as a header or bottom-left and bottom-right stretch to replace the area reserve for close button as footer section of the element. These can make modifying the elements during production a lot easier and reduce the amount of rework that might be needed with the user interface.

Pivots

Pivot_point

So I made some modifications and made a footer section to the element which now contains the CloseButton that is now centered to the footer section.

Notice how the pivot-y of the footer is zero? This means that the position of the footer element is now based on the bottom-center which makes it easy to modify it’s width and height without having to constantly re-position it because of the change in dimensions.

Proper pivots with anchors also help a lot when you want to animate the elements. For example if you want to hide a certain element by re-positioning it off-screen to the right you could do it fairly easy with unity animations as you could just change the objects pivot during the animation to left-center and it’s anchor to right-side of the canvas and set the position-x to zero.

Project introduction: FunUI

I’ve been working quite a bit with the user interface system Unity released with their version 4.6 and before that I worked extensively with the NGUI that the current system is based. The UGUI as some call it has been a big improvement over the OnGUI systems that were used back in the day.

However I have seen a lot of Unity games in GameJams, Greenlight and Itch.io really lacking when it comes to user interface.  Sure many of these games made by hobbyist or less experienced game developers and programmers but a lot of these games could be a lot better if there where more (Free) generic re-usable elements available.

So I decided to start a project that aims to remedy at least some of these  problems by offering some more or less generic re-usable customizable components, elements, features along with some examples on how to use them to build a more rigid and flexible user interface for games.

Current progress

  • I started off by making a Window element that user can drag and resize as well as minimize, maximize and close.
  • Then made a generic Form element that stores references for controls/components found in child objects like Text, Slider, Button, Image, toggle etc which makes them fairly easy to access and modify on run-time.
  • Made few dialog boxes for notices, confirmations, naming
  • Started working on a simple settings window where user could change the control settings of the game.
  • Which wasn’t as easy as I though it would be because Unity doesn’t allow changing built in inputs on run-time so had to make input system of my own.

 

The project has already given me some ideas on what to talk about on this blog. The project will be freely available and open source some time in the future.

Some tips for intractable Game Elements

No matter what kind of game you’re making for whatever platform whether it’s mobile or a desktop device it’s likely that the game contains Intractable Game elements. By these I mean elements the player can interact with either through clicking, touching or maybe through pressing a certain button while near the element. For example: characters, items, switches, players or even elements in the user interface.

It’s important to get the hierarchy with these elements right, because often these elements get surrounded by all sorts of problems usually related to animation, scale, collisions or just way too many exceptions.

Bad Hierarchy

Below is an example of a really bad hierarchy for game element. There’s basically no hierarchy at all with all components attached to the parent object.

Click_tutorial_1
This might be enough for really simple objects found in hastily build up prototypes but more you use them and more complex you make them the more you’ll eventually run in to problems.

Few examples:

  1. Conflicts with the animations that modify the scale, rotation and position which you’d also like to access from your games logic.
  2. Problems with non-uniform scales which can cause a lot of unwanted weird behavior in attached child transforms.
  3. Problems with the default pivots and rotations of 3D-models e.g characters pivot is on the center of the character instead of it’s feet or character is not facing the direction it should when attached to a transform.
  4. Problems with unwanted colliders intercepting touch or click ray-casts.
  5. Physical size of the element itself could be too small and make it difficult to hit on small screens.

A lot of these problems can be solved by separating stuff like game logic, animation, interaction and user interface with a proper hierarchy.  There are many ways to do this and it’s easy to get carried away and make the hierarchy just too complex.

Below is example of the sort of hierarchy I often use in Unity3D

Click_tutorial_3

As you can probably see from the example above I like to keep the root transform fairly light. It’s also the place where I tend to put most of my game logic related to the element itself. This makes game logic easy to access from components in child transforms using:

GameElementBehavior element = transform.root.GetComponent<GameElementBehavior>();

As for rigidbodies, it’s generally recommended to keep them in the parent transform unless so that modifying the parent transforms properties won’t conflict with the physics simulation.

From the example you can also see that I tend to separate the model or in this chase sprite to it’s own game object below the parent transform. It’s usually the place where I’ll keep the animator component as well and components that listen to animator events, state or anything related to animation. This is also good place to place physical collider because sometimes you want to modify it to represent the animation e.g make it smaller when character is crouching.

Click_tutorial_2

Then if for example I need to make the element clickable i’ll simply separate that behavioral logic to it’s own child game object. This allows me to easily modify the size of the touch area by resizing the collider. I also recommend using a different layer like the UI layer for this game object and modifying the Hit-mask in Physics ray-caster attached to the camera  to only hit that specific layer.

Other things you could seperate like this are colliders for detecting hits from/to enemies or radar like trigger area around the player for disabling and enabling points of interest or systems for handling particle effects like smoke if the element has taken damage or is under a magic spell.

InteractableBehavior.cs


using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;

public class InteractableBehavior : MonoBehaviour, IPointerClickHandler
{
    public UnityEvent OnRightClick;
    public UnityEvent OnLeftClick;
    public void OnPointerClick(PointerEventData eventData)
    {       
        if (OnLeftClick != null && eventData.pointerId == -1)
            OnLeftClick.Invoke();

        if (OnRightClick != null && eventData.pointerId == -2)
            OnRightClick.Invoke();
    }
}

GameElementBehavior.cs

using UnityEngine;

public class GameElementBehavior : MonoBehaviour
{
    public void ScaleUp()
    {
        if (transform.localScale.magnitude < 3.0f)
            transform.localScale += Vector3.one * 0.1f;
    }

    public void ScaleDown()
    {
        if(transform.localScale.magnitude > 0.3f)
            transform.localScale -= Vector3.one * 0.1f;
    }
}

Notes:

For InteractableBehavior to work you need:

Getting rid of unnecessary singletons

I have often stumbled people using singletons for a lot of stuff when developing games with Unity. Most often they’re used for convenient access to all sorts of stuff like Game Managers, UI Managers, Game sessions handlers and Save systems. This is all fine and dandy for a while but as your code base grows longer you start to appreciate more loosely coupled code and maybe even do some unit testing.

Most Unity tutorials tend to always use public properties and/or FindObjectOfType to access other unity objects. However relying solely on these tends to make the code feel really messy and writing the same code to find certain object in the scene for the umpteenth time should ring DRY alarm for everyone.

However there’s a simple solution which is called the Toolbox which is at its core a static container class that just contains references to bunch of tools that you want easy access to from everywhere from your code.

The example in Unity3D wiki is all good, but in my opinion it’s a bit too complex to convey the basic idea behind a toolbox. So made a very stripped version with C# showing how you can make a simple toolbox to your game or software.

It’s a simple static class that uses public static properties with lazy initialization for tools.

public static class ToolBox
{
    static GameManager _gm;
    public static GameManager GM
    {
        get
        {
            if(_gm == null)
            {
                GameObject ob = new GameObject("GameManager");
                GameObject.DontDestroyOnLoad(ob);

                _gm = ob.AddComponent<GameManager>();
            }
            return _gm;
        }
    }

    static SaveSystem _saveSystem;
    public static SaveSystem MainSaveSystem
    {
        get
        {
            if (_saveSystem == null)
                _saveSystem = new SaveSystem("SaveData");

            return _saveSystem;
        }
    }
}

With this you could access your GameManager and SaveSystem from anywhere simply anywhere in your code like like this:

ToolBox.GM.ResetGame();
ToolBox.MainSaveSystem.SaveGame();

This should be much cleaner and more loosely coupled than relying on multiple singletons. None of the tools themselves are singletons so if you for some reason need a dozen game managers in your game in future (e.g one for each player) you can do that.  You could also change any of the tools with different versions without having to modify code elsewhere, provided that the versions contain the same methods or the same interface.

First blog post

It’s finally here, after thinking long and hard whether to make one of these or not I decided to go for it and finally start a more technical oriented blog about game development and computer programming.

First I thought about writing the blog completely in Finnish but decided against it for possibly wider audience.  Might still make a tutorial or two for beginners in Finnish to maybe help those not as fluent in English to try out programming but who knows.

I’ll be updating this on whenever I feel like basis at least in the beginning because I don’t want to get all stressed out by it which I hope will make the content a lot more meaningful.