Unity Cookbook. User interface

User interface

Unity UI

  • A package for creating User Interface (UI) components
    • contained in new Unity projects by default
  • For elements that stay in constantly on screen
    • HP bars, menu buttons…
  • Packages: Unity UI

Canvas

  • UI elements are drawn on a separate canvas and on a separate layer
    • Canvas represents the rectangular area in which the UI is drawn
    • More about it later!
  • Create a new Canvas GameObject with GameObject > UI > Canvas
  • Packages: Unity UI: Canvas

Canvas GameObject

  • The Canvas GameObject has these components by default
    • Rect Transform
    • Canvas
    • CanvasScaler
    • Graphic Raycaster

Rect Transform Component

  • Packages: Unity UI: Rect Transform
  • UI counterpart for the Transform component
    • Has width and height as well
    • (RectTransform inherits from Transform!)
  • Has also anchor points for aligning with the canvas, or a parent UI GameObject

Canvas Component

  • Packages: Unity UI: Canvas class
  • Render mode: Screen space vs World space
    • Screen space
      • UI elements are rendered to fixed place on the screen, on top of the scene
    • World space
      • UI elements are hanging out with other GameObjects
      • “Diegetic interface”
  • Order in Layer: Change this to arrange which UI elements are drawn on top
    • Note: You can add a new canvas component to an UI component inside a canvas and change its sorting order!

CanvasScaler Component

  • Packages: Unity UI: CanvasScaler

  • Important setting: UI Scale mode

    • Constant pixel size
      • UI elements take the same amount of pixels regardless of screen size
    • Constant physical size:
      • UI elements take the same amount of pixels/DPI regardless of screen size
    • Scale with screen size:
      • UI elements take a given portion of the screen size
      • This is the one we usually want
      • You can choose if you rather match the screen width or screen height with Screen Match Mode

Graphic Raycaster Component

  • The Graphic Raycaster is used to raycast against a Canvas.
  • The Raycaster looks at all Graphics on the canvas and determines if mouse is top on any of them
  • Graphic Raycaster
  • Can be used to determine if the cursor is over a Graphics element in the Scene:

Visual components

  • These are used for actually drawing things in the UI
  • Packages: Unity UI: Visual Components
  • Add e.g., image to scene with GameObject > UI > Image
    • All UI element GameObjects have to be under the Canvas GameObject!

TextMeshPro

  • Packages: TextMeshPro user guide
  • There are two ways to draw text to UIs in Unity
    • The legacy Text GameObject that is easier to use
    • The newer, more feature-packed Text - TextMeshPro
  • TextMeshPro is a separate package that comes with new Unity Projects by default
  • To start using it, install TextMeshPro Essentials
    • A prompt will appear when you add a TextMeshPro GameObject
    • If you missed it, install it manually with Window > TextMeshPro > Import TextMeshPro Essential Resources

TextMeshPro: Using a custom font

  • You need to create a new font asset before you can use your own font with TextMeshPro

1) Add your font file (.ttf, for example) to your Assets folder 2) Open Window > TextMeshPro > Font Asset Creator 3) Drag the font file to Source Font File 4) Click Generate Font Atlas 5) Click Save to save the generated Font assets

  • Now you can set the new font asset to a TextMeshPro component!

Updating UI with code

  • You can update the text field of a TextMeshPro component with code:
    [SerializeField] TextMeshProUGUI textComponent;
    ...
    public void setScore(int newScore)
    {
        textComponent.text = $"Score: {newScore}";
    }
    
  • Note: To use the TextMeshProUGUI component, you need to add using TMPro; on top of the script file.

UI manager

  • We usually want to create a UI manager that handles updating the UI
    • For instance with a name UIManager
  • We can make it a singleton with a name instance to access it easily from wherever we want to use it in the game

using TMPro;

public class UIManager : MonoBehaviour
{
    public static UIManager instance;

    [SerializeField] TextMeshProUGUI scoreText;
    public int score = 0;

    void Start()
    {
        if (instance != null) Destroy(gameObject);
        else instance = this;
    }

    public void UpdateScore(int scoreChange)
    {
        score += scoreChange;
        scoreText.text = score.ToString();
    }
}

Interaction components

Creating functionality with the UI

  • Functional UI GameObjects can be connected to your other GameObjects
  • For example, for the Button GameObject: 1) Inspector > Button Component > On Click() 1) Press “+” 1) Drag your GameObject to None 1) Choose function from list to call when button is clicked

Invoking button press by pressing a controller button

  • Use this script to invoke UI button press with a controller even though the UI button wasn’t really pressed:
    [SerializeField] Button _button;
    ...
    if (Input.ButtonDown("Fire1"))
    _button.onClick.Invoke();
    
  • By default, your buttons are only interactable with mouse
  • To add support controller & keyboard input, you need to do two things:
    • In every button, set Navigation to Automatic
      • You can visualize button navigation flow with Visualize
      • If Automatic doesn’t give desired results, try other options.
    • Then, drag the button you want to be highlighted first to your Event System GameObject’s First Selected property
  • Extra stuff:

More RectTransform stuff

Rect Transform position

  • RectTransform.position is the world space position
  • RectTransform.localPosition is the position relative to its parent
  • RectTransform.anchoredPosition is the screen space position of the pivot of relative to the anchor reference point

Rect Transform Anchor points

  • Packages: Unity UI: Basic Layout
  • RectTransform Uses Anchors: four small triangular handles in the Scene View
    • Anchors can be set from the Scene view, with the Anchor presets, or from the Inspector
    • See the link above and mess around with anchors while doing so!

UI Example: HP bar

  • RectTransform: Set pivot to left
  • Control the HP bar width from code:
    hpBarRT = GetComponent<RectTransform>();
    ...
    public void AddHP(float newHP)
    {
        hp += newHP;
        hp = Mathf.Clamp(hp, 0, 100);
        hpBarRT.sizeDelta = new Vector2(width * hp / 100, hpBarRT.rect.height);
    }
    
  • Use 9-Slicing for HP bar art

UI Example: Dialogue system


  void StartDialogue()
  {
    index = 0;
    StartCoroutine(coTypeLine);
  }

  IEnumerator TypeLine()
  {
    foreach (char c in lines[index].ToCharArray())
    {
      textComponent.text += c;
      yield return new WaitForSeconds(textSpeed);
    }
  }

  void Update()
  {
    if (Input.GetButtonDown("Fire1") && (textComponent.text == lines[index]))
    {
      NextLine();
    }
    if (Input.GetButtonDown("Fire2") && (textComponent.text != lines[index]))
    {
      StopCoroutine(coTypeLine);
      textComponent.text = lines[index];
    }
  }
  void NextLine()
  {
    if (index < lines.length - 1)
    {
      index++;
      textComponent.text = "";
      StartCoroutine(coTypeLine);
    }
  }

UI Gotchas!

There’s a weird white box surrounding my UI elements

  • Turn off the Canvas Gizmo in Play mode, under the Gizmos dropdown menu.

My sprite is moving wildly when I resize the screen

  • You have to change the Anchor presets
  • Inspector > Rect Transform and click on the square on the left
    • Pressing down Shift+Alt exposes additional options

I can’t press my buttons!

  • When clicking on buttons doesn’t work, you might have invisible UI elements on top of the button that block clicking on the buttons underneath.

UI exercise 1: Basics

Continue the Exercise 3 from Collision. Create a counter for the collected items that sits on the top left corner of the screen.

See how UI scaling changes when you change the CanvasScaler component settings!

UI exercise 2: Buttons

Create a UI with three buttons.

Change the color of a GameObject in your scene when the button has been pressed!

Try out setting RectTransform anchor points and see how the UI changes when you change the game resolution in the Game view.

Reading

Extra: IMGUI - Immediate Mode Graphical User Interface

  • Code-driven system to create UI elements quickly
  • Manual: GUI scripting guide
  • ScriptReference: GUI
  • Example: Button
    if (GUI.Button(new Rect(100, 30, 150, 30), "Do a thing!"))
    {
        // When button is pressed, do a thing here
    }
    
  • Example: Input Field
    value = GUI.TextField(new Rect(300, 30, 200, 20), value, 25);
    

width:700px

  • This is the kind of elements you can create with IMGUI.

Extra: UI toolkit

  • UI Toolkit
    • Collection of features, resources, and tools for UI
      • Create UIs with style sheets