Monthly Archives: May 2016

Speech Bubbles and Popup UI

Many games show dialogue with a popup speech bubble, or prompt you to press an action button when you approach an object. In this tutorial I’ll show you how to create a popup UI object that can be used for any kind of popup need in your Unity game, using Unity’s flexible UI system.

Intermediate level: I will use standard Unity terms (e.g. “trigger collider” or “Inspector”) without explaining them, and you should know at least a small amount of C# code. If you’re a total beginner, check out my Pong tutorial for beginners.

Here’s how it will look in a game:

Speech bubble

Speech bubble

There are countless uses for world space UI, such as buttons that provide interaction for certain objects, helper UI showing the player what button to press, and much more.

This tutorial is in 2D, but I’ve included an extra script required to get the functionality working properly in 3D. A full demo Unity project is linked at the end, including samples in 2D and 3D.

What we’ll be doing

We’ll use Unity’s UI system in ‘world space’ mode to show UI canvases within the game world (rather than overlaying the whole screen like a menu or control buttons).

This demo will use characters that will talk to the player via speech bubbles when the player approaches.

The great thing about using UI like this is that you can dynamically change the UI very easily. The character needs to say something different? Just change the text in the UI Text component.

Check out the Unity UI canvas tutorial for a quick (6 minute) video overview.

 Start the Project

Start up Unity and create a new project with 2D settings.

Next, build up a character who will talk to the player:

  1. Add an empty GameObject to the scene and call it ‘NPC’ (non-player character).
  2. Give the NPC a SpriteRenderer component and add a sprite of your choosing.
  3. Add a UI Canvas to NPC (right-click NPC in the Hierarchy > UI > Canvas).
  4. Select NPC’s canvas in the Hierarchy by clicking it.

World Space Canvas Settings

Change the canvas’s settings to match mine in the image below. You may want to adjust yours slightly depending on the size of your NPC sprite or screen setup, so take my scale and size values as guides, not definitive. The settings to set are within the red boxes.

  • Set the canvas Render Mode to World Space.
  • Change the canvas scale to 0.05 on all axes.
  • Change the canvas position to [0,0,0] (i.e. the same position as the parent GameObject)
  • Adjust the width and height to about 200×100.
World space canvas settings

World space canvas settings

When your settings are right, you should see something similar to this in the Scene window when you select the canvas in the Hierarchy:

image.png

The canvas is the grey box sitting above the giraffe’s head. The speech text will go inside the canvas. If you don’t get a suitable size/shape for the canvas, tweak those settings and make sure the position is [0,0,0].

 Add Some Text

Add a UI Panel component to the NPC’s canvas.

You can leave the panel at the default grey shading, or even better add a speech bubble image to its Image component like I’ve used (you can use the image in the sample project). If you use an image you might need to adjust the canvas positioning so it looks right. You can also tint the panel to give your speech bubble more character.

image_thumb.pngNext, right-click the Canvas component and select UI > Text to add a Text component. Add some text, then tweak the size of the Text component to ensure it looks good. I recommend centering the text and using a fun font.

Adding a font to Unity is easy – just place it anywhere in your Assets folder, and it becomes available for any Text components in your game. Here’s how mine looks:

image_thumb.png

Customisable

You’ve created the speech bubble with some hard-coded text, but remember that the benefit of using a canvas here is that you can easily change the text via scripting (e.g. if your player will be having conversations with other characters).

A Fun Example

World space UI is great by itself, but let’s make it more fun with an example. We’ll make the speech bubble display only when the player is close to the NPC character.

Here’s what we need to do:

  1. Create a simple player that can move around the screen.
  2. Detect when the player is near to the NPC and turn the canvas on.

Create the Player

  1. Add a new empty GameObject to the scene and call it ‘Player’.
  2. Add a sprite to Player (anything you want).
  3. Add a Rigidbody2D (this is required to enable trigger collider physics)Set the gravity scale to 0. This is required in this sample because of the way I’m setting up movement; it has nothing to do with the actual UI display technique.
  4. And a CircleCollider2D (you can use any collider shape, but I used a circular sprite, so a circle was best).

Finally, you need to create a new C# script called DemoController.cs, and add it to the player. Here is the full script code. It simply moves the player around on X and Y axes according to keyboard or game controller input:


using UnityEngine;
using System.Collections;

public class DemoController : MonoBehaviour {

[SerializeField]
private float speed;

enum MoveDir
{
    None,
    Up,
    Down,
    Left,
    Right
}

void Update()
{
    GetInput();
}

void GetInput()
{
    if (Input.GetAxis("Horizontal") > 0.2f)
    {
        Move(MoveDir.Right);
    }

    if (Input.GetAxis("Horizontal") < -0.2f) { Move(MoveDir.Left); } if (Input.GetAxis("Vertical") > 0.2f)
    {
        Move(MoveDir.Up);
    }
    if (Input.GetAxis("Vertical") < -0.2f)
    {
        Move(MoveDir.Down);
    }
}

void Move(MoveDir moveDir)
{
    var movement = Vector3.zero;
    switch (moveDir)
    {
        case MoveDir.Down:
            movement = new Vector3(0, -1f,0);
            break;
        case MoveDir.Up:
            movement = new Vector3(0, 1f,0);
            break;
        case MoveDir.Left:
            movement = new Vector3(-1f, 0, 0);
            break;
        case MoveDir.Right:
            movement = new Vector3(1f, 0, 0);
            break;
        default:
            return;
    }

    transform.Translate(movement*speed * Time.deltaTime);
  }
}

Test your scene. You should be able to move the player around the screen with the arrow keys or a gamepad.

 Update your NPC

Currently, the NPC’s speech bubble is visible. We want it to display only when the player is nearby. Let’s make a few adjustments to the NPC to make this happen.

Add a CircleCollider2D to the NPC GameObject.

  • Make the collider larger than the sprite so it acts as a ‘zone’ that triggers speech when the player enters.
  • Tick the Is Trigger box on the component so that the collider is in trigger mode.

Here’s the size I used for my collider (the green circle):

image.png

Script the Interaction

Create a new script called InteractiveObject.cs and paste in the following code:


using UnityEngine;
using System.Collections;
public class InteractiveObject : MonoBehaviour
{
    [SerializeField]
    Canvas messageCanvas;

    void Start()
    {
        messageCanvas.enabled = false;
    }

    void OnTriggerEnter2D(Collider2D other)
    {
        if (other.name == "Player")
        {
            TurnOnMessage();
        }
    }

    private void TurnOnMessage()
    {
        messageCanvas.enabled = true;
    }
        
    void OnTriggerExit2D(Collider2D other)
    {
        if (other.name == "Player")
        {
            TurnOffMessage();
        }
    }

    private void TurnOffMessage()
    {
        messageCanvas.enabled = false;
    }
}

Basically it turns the canvas component on when the player enters the trigger zone and off when the player leaves. The canvas is turned off when the scene starts (but I find it useful to have the canvas on by default when working in the Unity editor).

Add a copy of that script to your NPC GameObject.

Select the NPC, then drag its Canvas from the Hierarchy into the empty Message Canvas slot on the Interactive Object script in the Inspector so the script knows which canvas to turn on and off.

Note that we are checking for the player object by name, so make sure your player GameObject is named “Player”.

Test the Scene

Now test the scene. If all has gone according to plan your NPC character should speak when the player object gets close to it:

giraffe3.gif

World space in 3D

To adapt this to 3D, you need one addition. In 3D games, a canvas could be facing in any direction, so the player won’t always see it. To get around this, you can add a short script to turn the canvas to face the camera so it’s always visible. Of course you’ll also replace the 2D physics with 3D equivalents. Attach the script below to any object with a world space UI if you want it to always face the player’s view (i.e. the camera).

There is a 3D demo scene in the sample project.

using UnityEngine;
using System.Collections;

public class SpeechBubbleRotate : MonoBehaviour
{
    Transform cameraTransform;

    void Start()
    {
        cameraTransform = Camera.main.transform;
    }

    void Update()
    {
        transform.rotation = Quaternion.LookRotation(transform.position - cameraTransform.position);
    }
}

Download

Here’s the full sample project including examples in 2D and 3d. All the art in the project is public domain (mostly from Kenney), as is the code, so do with it what you like.

Next Steps

Now that you know how to use a world space canvas to display UI inside your game area, you can use the technique in many ways. Here are some things you can try:

  • Add interactive UI (e.g. buttons) to the canvas.
  • Only show the UI if the player is in the trigger area and presses a button.
  • Build a fancy UI with lots of different UI elements to test out the functionality.