UI elements and their implementation

In this article by Francesco Sapio, author of the book Unity UI Cookbook, we will see often in games, there are menus that have shortcuts. For example, if the player has to use a skill quickly, he/she needs an easier way to access it. In general, where there is the possibility within the UI to choose more than one selectable elements, such as buttons and toggles, it is also possible to select them by a keyboard shortcut.

(For more resources related to this topic, see here.)

This will teach you how to detect when a key is pressed and select one specific UI element by creating a script. This script can be generic enough to be placed on every UI element without changing the code.

How to do it...

  1. To begin, create a new panel. Right-click on the Hierarchy panel and then go to UI | Panel. We can also rename it to keep the project names ordered.
  2. Next, we need to create a button inside the panel that we created before. We can do this by right-clicking on the panel and then going to UI | Button.
  3. In order to see better which button is currently selected, let's change some properties of the Button (Script) component. For instance, we could choose a different color for Normal Color, Highlighted Color, and Pressed Color. In this example, let's set Highlighted Color to red, set Pressed Color to green, and leave the Normal Color as white. Finally, we also need to change Navigation to Vertical.
  4. In order to have the ability to select among different buttons, we need different buttons in the scene. We can achieve this by duplicating the button. This can be done by pressing Ctrl + D. Then place the duplicated buttons below the original one. Rename the first of these to Button 1 and the second to Button 2. Do the same with the Text variable inside the Text (Script) component on the child of the button. As a result, we will be able to distinguish buttons on the screen also. Finally, repeat this step at least two more times in order to get three buttons. Once we are done, our scene should look similar to the following:

  5. Now, it's time to make our first script. To begin, in Inspector, go to Add Component | New Script, name it ButtonThroughKeySelection, and then click on Create and Add. In doing this, ensure that the language selected is C Sharp.
  6. Double click on the script in order to open it in MonoDevelop.
  7. Every time we work with some UI classes, we need to add a using clause on top of our script. This will ensure that we don't have any compilation error when the script is compiled by Unity. Furthermore, since we are also using events, we need to add another using clause. Therefore, at the beginning of our script, we need this:
    using UnityEngine.UI;
    using UnityEngine.EventSystems;
    using UnityEngine;
    using System.Collections;
  8. Moreover, we need to add a variable for the key that has been chosen. By doing this, we can set this variable in Inspector:
    public class ButtonThroughKeySelection: MonoBehaviour {
    
    public string key;
    
  9. Since we don't need to set the initial variables, we can erase the Start() function. In order to implement the detection of the pressed key and change the selected button, we need to write the Update() function in the following way:
    public void Update()
    if (Input.GetKeyDown (key))
    {
       EventSystem.current.SetSelectedGameObject(
                 this.gameObject);
    }
    } }
    }
    } // ends the class
  10. Now, we can save the script and add it to one of the three buttons.
  11. Next, set the Key variable with a string that represents a key, for example, space for the spacebar. Once we have done this, we should see something like the following:

  12. Finally, we can click on the play button and see whether everything works. After our button is selected by pressing the key bounded by the variable, we can move through the others with the arrow keys. However, if we re-press our key, which in this example is the spacebar, the selection returns on our button.

How it works...

To get started, we have created three buttons in the scene, which are our test buttons. We also changed some of the buttons' properties in order to clearly see the effect that our script has on the buttons. Since we had distributed our buttons vertically, we set the Navigation variable to Vertical.

At the beginning of the script that we wrote, we added the using UnityEngine.UI; and using UnityEngine.EventSystems; statements.

We added a public string variable. It was public so that it could be set in Inspector later. As a result, we can choose an arbitrary key to bind a specific button where the script is collocated.

Now, in the Update() function we checked through if (Input.GetKeyDown (key)) to see whether our key is pressed. In fact, the Input.GetKeyDown(string) function returns true if the key specified as a string is pressed, and false if it is not. It's important to remember that the key variable is set in Inspector, so it could change according to the design of our game. Check out the See also section for more information about key press detection.

Finally, if our key is pressed, we need to select a specific button. This can be done with the EventSystem.current.SetSelectedGameObject(this.gameObject); line. The first part, EventSystem.current, returns the current event system that is used. Then, we call on it the SetSelectedGameObject(gameObject)function, which selects the game object passed as a parameter. In this case, we use this.gameobject, which is the game object where this script is attached as well as the button we want to select.

By keeping everything parametric (such as the key variable, which can be set to every instance of the script), we are able to use this script on many buttons every time and customize it differently, without touching the code again.

See also

Adding a circular mask to an image

Often in games, UI elements are not designed to be rectangular. Thus, a quick way to change their shape is through masking. One basic shape is a circle. This could be useful, for example, to surround a character icon circularly or to create special circle buttons. In order to achieve this, we will use the Mask component.

How to do it...

  1. First of all, we need to create a mask, which in this case should be circular. Since the mask is just another image, let's open a graphics program. Then, we need to create a new image with the same pixels for height and width so that the drawing canvas is a square.
  2. This and the following step depend on the graphic program you are using. Now, draw a white circle in the middle of the image.
  3. Furthermore, we should also ensure that the background is transparent. In the screenshot below, you can get an idea of what the outcome will look like.
  4. The program used in this screenshot is Photoshop:

    If you are using Photoshop, you can easy create this mask by using the ellipse tool. While holding the Shift key, click on the upper-left corner and drag it to the lower-right corner.

  5. The next step is to import this mask into the project. To do this, right-click on the Project panel and select Import new asset.
  6. Unity will ask us to select the mask that we have just created. Therefore, locate the folder to where you saved it and then import it.
  7. In order to see the settings of the imported mask as an image in Inspector, we need to select it in the Project panel.
  8. Thus, if our project is not set in 2D,, we should change Texture Type in Sprite (2D and UI) in Inspector. Then click on Apply.
  9. Now, we need to create a new panel. We can do this by right-clicking on the Hierarchy panel and then going to UI | Panel. We should also ensure that we have it inside the Canvas object.
  10. Inside the Image (Script) component, we need to set our mask to the Source Image variable.
  11. In order to get the exact shape that we created in our graphic program, we need to bring the image back to its original proportions. This can be done by clicking on Set Native Size and then scaling uniformly (by keeping Shift pressed) if needed.
  12. The next thing to do is transform our panel into a mask. So, we need to add the Mask (Script) component to our panel.
  13. Then we also need the image to put the mask on. Therefore, let's create an image inside the panel. To do this, we need to right-click on the panel in Hierarchy and then navigate to UI | Image.
  14. Inside the Image (Script) component of the image, we need to select the picture we want to mask. This can be done by dragging it into the Source Image variable of the component. As a result, it will be masked with a circle.
  15. If needed, we can click on Set Native Size and scale it uniformly.
  16. In this case, by using an ancient map, we can see what the final outcome should look like in the following picture:

How it works...

As we have seen, Unity uses another image to create the mask. This is the reason the Mask (Script) component is attached to the object that has an Image (Script) component. As a result, it is possible to create any shape that we want for the mask. In fact, we only need to keep in mind that the white sections of the mask texture will be the parts that are visible.

See also

Implementing a score counter

We are going to create a score counter that displays the score as a number on the screen. To achieve this, we will use the Text (Script) component and create a script to handle it. Different functions will be available from this script and will be called from other scripts to increase the score.

How to do it...

  1. First of all, we need to create new UI text to display our score. Thus, right-click on the Hierarchy panel and then go to UI | Text. Finally, rename it to ScoreCounter.

    To rename an object, right-click on it and select Rename. Otherwise, we can change its name in Inspector.

  2. Next, we can change Font and Font Size in Inspector as we wish to better suit our needs.
  3. Furthermore, we should also adjust Color. In this example, we will set it to white in order for it to be easily visible within the scene.
  4. Now, we need to drag ScoreCounter with Rect tool (the hotkey for this tool is T) where we want to place it.
  5. We can write the word Score in the Text variable. In fact, this helps us visualize what the counter will look like even though this value will be replaced by the script that we are going to write in the next steps.
  6. Ensure that the Rich Text variable is checked. This allows us to use different colors inside the counter.
  7. In this step, we need to create a script that manages the score. Navigate to Add Component | New Script in Inspector and name it ScoreCounterScript. Then click on Create and Add. In doing this, ensure that the language that is selected is C Sharp.
  8. Double click on the script in order to edit it. Since we are going to use the Text class, we need to add the using UnityEngine.UI; statement at the beginning of the script.
  9. Before we add the functions to our script, we need two private variables. Hence, we can write these lines:
    private Text uiText;
    private long score = 0;
  10. In the Start() function, we can set store ScoreCounter in the uiText variable so that we can refer to it later in the script. In addition, we need to update our score, so let's call a function that we will write later. Thus, here is the Start() function:
    void Start () {
       uiText = this.GetComponent<Text> ();
       updateScoreCounter ();
    }
  11. Next, we need a function for adding points to our score counter, which can be called from other scripts. We pass to it an int parameter, which is the number of points the player has earned. So, we can write this:
    public void addPoints(int points){
       score += points;
       updateScoreCounter ();
    }
  12. Finally, since we have called the updateScoreCounter() function twice, it's time to write it down:
    private void updateScoreCounter(){
       uiText.text = "<color=blue>Score</color>: " + score;
    }
  13. We can save the script and our work is done. We should see something like this:

How it works...

In the script, there are two variables, uiText and score, which we've set to private because they need not be accessed by other components. The former stores the reference to the Text (Script) component in order to get it later in the script. The latter is the score of the player. It is a long variable that allows us to store big numbers, since in some games, score points are very huge numbers.

The Start() function in Unity is special, since it is called only once—when the script is enabled for the first time. In this function, we assign the Text (Script) component attached in the same game object of this script to the uiText variable, by calling the this.GetComponent<Text>() function. Then, we call the updateScoreCounter() function in order to update the User Interface.

Moreover, we added the addPoints(int points) function. It takes an int variable as a parameter, named points. Then, the function adds this value to the score variable through score += points;. Finally, we call updateScoreCounter() to update the interface. The += operator will take the value that score currently has and increase it by whatever is in our points value.

Finally, the updateScoreCounter() function changes the text variable on the Text (Script) component stored in the uiText variable. In fact, the new value assigned is a string. In the first part of this function, there is <color=blue>Score</color>:. This encloses the word Score in styling tags so as to change its color to blue. Of course we can also change blue to any other color as we prefer. Finally, we added the score; don't worry about the score variable being long, because in this case, Unity converts the number automatically to a string.

There's more...

Adding a remove points function

In some games, there is a possibility of losing points, but we should be careful not to cause a negative score.

Thus, we can deal with this issue by adding a new function to our script:

public void removePoints(int points){
   score -= points;
   if (score < 0)
     score = 0;
   updateScoreCounter ();
}

With an if statement, we check whether our score is negative; if so, we set it to zero, since we don't want a negative score.

Finally, we update the score counter by calling the updateScoreCounter() function.

Using boldface in rich text

The rich text of Unity allows us to change not only the color of a specific portion of text, but also the style. In order to give more importance to the word Score, we can replace this line of code inside the updateScoreCounter() function:

uiText.text = "<color=blue>Score</color>: " + score;

with this one:

uiText.text = "<b><color=blue>Score</color>:</b> " + score;

The text inside the <b> tag is now shown in boldface. Refer to the See also section for more details.

Getting the score

It could also be helpful to retrieve the score. For example, this is useful when we not only display it on the screen but also save it on a scoreboard. Since we have set the score variable as private, we cannot access it directly. It's good practice not to change the variable to a public, but to add a new get function instead. Here is how we can do this:

public long getScore(){
   return score;
}

We simply return the score value and the job is done.

See also

Implementing a numeric timer

We are going to create a timer that displays the time (as a number) on the screen. This may be a useful element when attempting to inform the player how much time has passed during an objective. In some cases, if a player is aware of how much time they are taking with a task, it may encourage them to be more efficient and considerate about their choices throughout the gameplay. To create a timer, we will use the Text (Script) component, as well as develop a script to implement the logic of the timer.

How to do it...

  1. First of all, we have to create a new UI text to show our timer. To do this, right-click on the Hierarchy panel and then go to UI | Text. Next, rename it to Numeric Timer.
  2. We can change the Font and Font Size as we wish to suit our needs.
  3. We can also adjust the Color. We will set it to white.
  4. Now, we can drag the Numeric Timer with Rect Tool to where we want to place it. In some cases, it is important to make a timer properly visible to a player. In other instances, it is a nice subtle addition to the UI.
  5. To display the timer better in the scene view, we can write the word "time" in the Text variable, even if this value will be replaced by the script. This is so that we have a better approximation of how it will look. It will help us to better gauge whether its placement will be effective, inhibit, or distract the player during gameplay.
  6. Next, we want to ensure that the Rich Text variable is checked. This is important in order to display the color of the text and also for us to observe the appearance of the timer within the game space.
  7. Now, we have to create a script that manages time. To do this, click on Add Component/New Script and then name it NumericTimerScript. Finally, click on Create and Add.
  8. Double-click on the script to edit it and, as always, add the using UnityEngine.UI; statement at the beginning of the script. This allows us to handle the UI elements within the script.
  9. Before we add any functions to the timer, we need to add two variables and make sure that we set them to private. So, we can write this:
    private Text uiText;
    private floattime;
  10. Next, we can set up the uiText variable in the Start() function. In fact, this is the ideal function for assigning the initial value to our variables, since it is called when the script runs for the first time in the game environment. Therefore, we can assign the reference to the Text (Script) component to the variable just before the timer starts, in the following way:
    void Start () {
       uiText = this.GetComponent<Text> ();
    }
  11. Now, we need to update our timer for each frame. This can be done by writing the following lines in the Update()function:
    void Update () {
       time += Time.deltaTime;
       uiText.text = "<color=blue>Time</color>: " + time.ToString("F2");
    }
  12. Finally, we can save the script, and our work is done. When we run the script, we should see something like this:

How it works...

First of all, we created a new UI text, and then adjusted it to suit our needs. We changed Font, Font Size, and also Color. In addition, we ensured that Rich Text was checked. In this way, it is possible to use different colors in the text of the timer. Then, we wrote a script to handle the timer.

In the script, there are two private variables: uiText and time. The uiText variable stores the reference to the Text (Script) component so that we can get access to it and modify its text. The time variable stores the amount of time that has passed since the timer started.

In the Start() function, we assigned the reference to the Text (Script) component, which is attached to the same game object of this script, to the uiText variable by calling the this.GetComponent<Text>() function.

Keeping in mind that the Update() function is called at every frame, we added Time.deltaTime, which is the time that has elapsed from the last frame to the time variable. We did this to accumulate the time that has passed since this script/timer started. In the second line, we updated the text variable on the Text (Script) component, which we can have access to through the uiText variable, with the new time value. Since we don't want all the decimal points, we have to cut the float by calling ToString("F2") on it.

There's more...

Getting the time variable

For some reason, we may want to retrieve the value of the time variable, such as when we want to trigger an event in our game environment or to pass its value to another script. We can achieve this by implementing a get function, like this:

public float getTime(){
   return time;
}

See also

Summary

We learned you how to add a circular mask to an image, to implement a score counter and, to implement numeric timer.

Resources for Article:


Further resources on this subject:


You've been reading an excerpt of:

Unity UI Cookbook

Explore Title