Home Game Development Unity 5.x Cookbook

Unity 5.x Cookbook

By Francisco Queiroz , Matthew Smith , Matt Smith and 1 more
books-svg-icon Book
eBook $47.99 $32.99
Print $60.99
Subscription $15.99 $10 p/m for three months
$10 p/m for first 3 months. $15.99 p/m after that. Cancel Anytime!
What do you get with a Packt Subscription?
This book & 7000+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with a Packt Subscription?
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with eBook + Subscription?
Download this book in EPUB and PDF formats, plus a monthly download credit
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with a Packt Subscription?
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with eBook?
Download this book in EPUB and PDF formats
Access this title in our online reader
DRM FREE - Read whenever, wherever and however you want
Online reader with customised display settings for better reading experience
What do you get with video?
Download this video in MP4 format
Access this title in our online reader
DRM FREE - Watch whenever, wherever and however you want
Online reader with customised display settings for better learning experience
What do you get with video?
Stream this video
Access this title in our online reader
DRM FREE - Watch whenever, wherever and however you want
Online reader with customised display settings for better learning experience
What do you get with Audiobook?
Download a zip folder consisting of audio files (in MP3 Format) along with supplementary PDF
What do you get with Exam Trainer?
Flashcards, Mock exams, Exam Tips, Practice Questions
Access these resources with our interactive certification platform
Mobile compatible-Practice whenever, wherever, however you want
BUY NOW $10 p/m for first 3 months. $15.99 p/m after that. Cancel Anytime!
eBook $47.99 $32.99
Print $60.99
Subscription $15.99 $10 p/m for three months
What do you get with a Packt Subscription?
This book & 7000+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with a Packt Subscription?
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with eBook + Subscription?
Download this book in EPUB and PDF formats, plus a monthly download credit
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with a Packt Subscription?
This book & 6500+ ebooks & video courses on 1000+ technologies
60+ curated reading lists for various learning paths
50+ new titles added every month on new and emerging tech
Early Access to eBooks as they are being written
Personalised content suggestions
Customised display settings for better reading experience
50+ new titles added every month on new and emerging tech
Playlists, Notes and Bookmarks to easily manage your learning
Mobile App with offline access
What do you get with eBook?
Download this book in EPUB and PDF formats
Access this title in our online reader
DRM FREE - Read whenever, wherever and however you want
Online reader with customised display settings for better reading experience
What do you get with video?
Download this video in MP4 format
Access this title in our online reader
DRM FREE - Watch whenever, wherever and however you want
Online reader with customised display settings for better learning experience
What do you get with video?
Stream this video
Access this title in our online reader
DRM FREE - Watch whenever, wherever and however you want
Online reader with customised display settings for better learning experience
What do you get with Audiobook?
Download a zip folder consisting of audio files (in MP3 Format) along with supplementary PDF
What do you get with Exam Trainer?
Flashcards, Mock exams, Exam Tips, Practice Questions
Access these resources with our interactive certification platform
Mobile compatible-Practice whenever, wherever, however you want
  1. Free Chapter
    Core UI – Messages, Menus, Scores, and Timers
About this book
Unity 5 is a flexible and intuitive multiplatform game engine that is becoming the industry's de facto standard. Learn to craft your own 2D and 3D computer games by working through core concepts such as animation, audio, shaders, GUI, lights, cameras, and scripting to create your own games with one of the most important and popular engines in the industry. Completely re-written to cover the new features of Unity 5, this book is a great resource for all Unity game developers, from those who have recently started using Unity right up to game development experts. The first half of the book focuses on core concepts of 2D game design while the second half focuses on developing 3D game development skills. In the first half, you will discover the new GUI system, the new Audio Mixer, external files, and animating 2D characters in 2D game development. As you progress further, you will familiarize yourself with the new Standard Shaders, the Mecanim system, Cameras, and the new Lighting features to hone your skills towards building 3D games to perfection. Finally, you will learn non-player character control and explore Unity 5's extra features to enhance your 3D game development skills.
Publication date:
October 2015
Publisher
Packt
Pages
570
ISBN
9781784391362

 

Chapter 1. Core UI – Messages, Menus, Scores, and Timers

In this chapter, we will cover:

  • Displaying a "Hello World" UI text message

  • Displaying a digital clock

  • Displaying a digital countdown timer

  • Creating a message that fades away

  • Displaying a perspective 3D text message

  • Displaying an image

  • Creating UI Buttons to move between scenes

  • Organizing images inside panels and changing panel depths via buttons

  • Displaying the value of an interactive UI Slider

  • Displaying a countdown timer graphically with a UI Slider

  • Displaying a radar to indicate the relative locations of objects

  • Creating UIs with the Fungus open-source dialog system

  • Setting custom mouse cursor images

  • Input Fields component for text entry

  • Toggles and radio buttons via Toggle Groups

 

Introduction


A key element contributing to the entertainment and enjoyment of most games is the quality of the visual experience, and an important part of this is the User Interface (UI). UI elements involve ways for the user to interact with the game (such as buttons, cursors, text boxes, and so on), as well as ways for the game to present up-to-date information to the user (such as the time remaining, current health, score, lives left, or location of enemies). This chapter is filled with UI recipes to give you a range of examples and ideas for creating game UIs.

The big picture

Every game is different, and so this chapter attempts to fulfill two key roles. The first aim is to provide step-by-step instructions on how to create a wide range of the Unity 5 UI elements and, where appropriate, associate them with game variables in code. The second aim is to provide a rich illustration of how UI elements can be used for a variety of purposes, so that you can get good ideas about how to make the Unity 5 UI set of controls deliver the particular visual experience and interactions for the games that you are developing.

The basic UI elements can provide static images and text to just make the screen look more interesting. By using scripts, we can change the content of these images and text objects, so that the players' numeric scores can be updated, or we can show stickmen images to indicate how many lives the player has left, and so on. Other UI elements are interactive, allowing users to click on buttons, choose options, enter text, and so on. More sophisticated kinds of UI can involve collecting and calculating data about the game (such as percentage time remaining or enemy hit damage; or the positions and types of key GameObjects in the scene, and their relationship to the location and orientation of the player), and then displaying these values in a natural, graphical way (such as progress bars or radar screens).

Core GameObjects, components, and concepts relating to Unity UI development include:

  • Canvas: Every UI element is a child to a Canvas. There can be multiple Canvas GameObjects in a single scene. If a Canvas is not already present, then one will automatically be created when a new UI GameObject is created, with that UI object childed to the new Canvas GameObject.

  • EventSystem: An EventSystem GameObject is required to manage the interaction events for UI controls. One will automatically be created with the first UI element.

  • Panel: UI objects can be grouped together (logically and physically) with UI Panels. Panels can play several roles, including providing a GameObject parent in the Hierarchy for a related group of controls. They can provide a visual background image to graphically relate controls on the screen, and they can also have scripted resize and drag interactions added, if desired.

  • Visual UI controls: The visible UI controls themselves include Button, Image, Text, Toggle, and so on.

  • Interaction UI controls: These are non-visible components that are added to GameObjects; examples include Input Field and Toggle Group.

  • The Rect Transform component: UI GameObjects can exist in a different space from that of the 2D and 3D scenes, which cameras render. Therefore, UI GameObjects all have the special Rect Transform component, which has some different properties to the scene's GameObject Transform component (with its straightforward X/Y/Z position, rotation, and scale properties). Associated with Rect Transforms are pivot points (reference points for scaling, resizing, and rotations) and anchor points. Read more about these core features below.

  • Sibling Depth: The bottom-to-top display order (what appears on the top of what) for a UI element is determined initially by their sequence in the Hierarchy. At designtime, this can be manually set by dragging GameObjects into the desired sequence in the Hierarchy. At runtime, we can send messages to the Rect Transforms of GameObjects to dynamically change their Hierarchy position (and therefore, the display order), as the game or user interaction demands. This is illustrated in the Organizing images inside panels and changing panel depths via buttons recipe in this chapter.

The following diagram shows how there are four main categories of UI controls, each in a Canvas GameObject and interacting via an EventSystem GameObject. UI Controls can have their own Canvas, or several UI controls can be in the same Canvas. The four categories are: static (display-only) and interactive UI controls, non-visible components (such as ones to group a set of mutually exclusive radio buttons), and C# script classes to manage UI control behavior through logic written in the program code. Note that UI controls that are not a child or descendent of a Canvas will not work properly, and interactive UI controls will not work properly if the EventSystem is missing. Both the Canvas and EventSystem GameObjects are automatically added to the Hierarchy as soon as the first UI GameObject is added to a scene.

UI Rect Transforms represents a rectangular area rather than a single point, which is the case for scene GameObject Transforms. Rect Transforms describe how a UI element should be positioned and sized relatively to its parent. Rect Transforms have a width and height that can be changed without affecting the local scale of the component. When the scale is changed for the Rect Transform of a UI element, then this will also scale font sizes and borders on sliced images, and so on. If all four anchors are at the same point, then resizing the Canvas will not stretch the Rect Transform. It will only affect its position. In this case, we'll see the Pos X and Pos Y properties, and the Width and Height of the rectangle. However, if the anchors are not all at the same point, then Canvas resizing will result in a stretching of the element's rectangle. So instead of the Width, we'll see the values for Left and Right—the position of the horizontal sides of the rectangle to the sides of the Canvas, where the Width will depend on the actual Canvas width (and the same for Top/Bottom/Height).

Unity provides a set of preset values for pivots and anchors, making the most common values very quick and easy to assign to an element's Rect Transform. The following screenshot shows the 3 x 3 grid that allows you quick choices about left, right, top, bottom, middle, horizontal, and vertical values. Also, the extra column on the right offers horizontal stretch presets, and the extra row at the bottom offers vertical stretch presets. Using the SHIFT and ALT keys sets the pivot and anchors when a preset is clicked.

The Unity manual provides a very good introduction to the Rect Transform. In addition, Ray Wenderlich's two-part Unity UI web tutorial also presents a great overview of the Rect Transform, pivots, and anchors. Both parts of Wenderlich's tutorial make great use of animated GIFs to illustrate the effect of different values for pivots and anchors:

There are three Canvas render modes:

  • Screen Space – Overlay: In this mode, the UI elements are displayed without any reference to any camera (there is no need for any Camera in the scene). The UI elements are presented in front of (overlaying) any sort of camera display of the scene contents.

  • Screen Space – Camera: In this mode, the Canvas is treated as a flat plane in the frustum (viewing space) of a Camera scene —where this plane is always facing the camera. So, any scene objects in front of this plane will be rendered in front of the UI elements on the Canvas. The Canvas is automatically resized if the screen size, resolution, or camera settings are changed.

  • World Space: In this mode, the Canvas acts as a flat plane in the frustum (viewing space) of a Camera scene—but the plane is not made to always face the Camera. How the Canvas appears is just as with any other objects in the scene, relative to where (if anywhere) in the camera's viewing frustum the Canvas plane is located and oriented.

In this chapter, we have focused on the Screen Space – Overlay mode. But all these recipes can equally be used with the other two modes as well.

Be creative! This chapter aims to act as a launching pad of ideas, techniques, and reusable C# scripts for your own projects. Get to know the range of Unity UI elements, and try to work smart. Often, a UI element exists with most of the components that you may need for something in your game, but you may need to adapt it somehow. An example of this can be seen in the recipe that makes a UI Slider non-interactive, instead using it to display a red-green progress bar for the status of a countdown timer. See this in the Displaying a countdown timer graphically with a UI Slider recipe.

 

Displaying a "Hello World" UI text message


The first traditional problem to be solved with a new computing technology is often to display the Hello World message. In this recipe, you'll learn to create a simple UI Text object with this message, in large white text with a selected font, and in the center of the screen.

Getting ready

For this recipe, we have prepared the font that you need in a folder named Fonts in the 1362_01_01 folder.

How to do it...

To display a Hello World text message, follow these steps:

  1. Create a new Unity 2D project.

  2. Import the provided Fonts folder.

  3. In the Hierarchy panel, add a UI | Text GameObject to the scene – choose menu: GameObject | UI | Text. Name this GameObject Text-hello.

    Note

    Alternatively, use the Create menu immediately below the Hierarchy tab, choosing menu: Create | UI | Text.

  4. Ensure that your new Text-hello GameObject is selected in the Hierarchy panel. Now, in the Inspector, ensure the following properties are set:

    • Text set to read Hello World

    • Font set to Xolonium-Bold

    • Font size as per your requirements (large—this depends on your screen—try 50 or 100)

    • Alignment set to horizontal and vertical center

    • Horizontal and Vertical Overflow set to Overflow

    • Color set to white

    The following screenshot shows the Inspector panel with these settings:

  5. Now, in the Rect Transform, click on the Anchor Presets square icon, which should result in several rows and columns of preset position squares appearing. Hold down SHIFT and ALT and click on the center one (row middle and column center).

  6. Your Hello World text will now appear, centered nicely in the Game panel.

How it works...

You have added a new Text-hello GameObject to a scene. A parent Canvas and UI EventSystem will also have been automatically created.

You set the text content and presentation properties, and use the Rect Transform anchor presets to ensure that whatever way the screen is resized, the text will stay horizontally and vertically centered.

There's more...

Here are some more details that you don't want to miss.

Styling substrings with Rich Text

Each separate UI Text component can have its own color, size, boldness styling, and so on. However, if you wish to quickly add some highlighting style to a part of a string to be displayed to the user, the following are examples of some of the HTML-style markups that are available without the need to create separate UI Text objects:

  • Embolden text with the "b" markup: I am <b>bold</b>

  • Italicize text with the "i" markup: I am <i>italic</i>

  • Set the text color with hex values or a color name: I am <color=green>green text</color>, but I am <color=#FF0000>red</color>

    Note

    Learn more from the Unity online manual Rich Text page at: http://docs.unity3d.com/Manual/StyledText.html.

 

Displaying a digital clock


Whether it is the real-world time, or perhaps an in-game countdown clock, many games are enhanced by some form of clock or timer display. The most straightforward type of clock to display is a string composed of the integers for hours, minutes, and seconds, which is what we'll create in this recipe.

The following screenshot shows the kind of clock we will be creating in this recipe:

Getting ready

For this recipe, we have prepared the font that you need in a folder named Fonts in the 1362_01_01 folder.

How to do it...

To create a digital clock, follow these steps:

  1. Create a new Unity 2D project.

  2. Import the provided Fonts folder.

  3. In the Hierarchy panel, add a UI | Text game object to the scene named Text-clock.

  4. Ensure that GameObject Text-clock is selected in the Hierarchy panel. Now, in Inspector, ensure that the following properties are set:

    • Text set to read as time goes here (this placeholder text will be replaced by the time when the scene is running.)

    • Font type set to Xolonium Bold

    • Font Size set to 20

    • Alignment set to horizontal and vertical center

    • Horizontal and Vertical Overflow settings set to Overflow

    • Color set to white

  5. Now, in the Rect Transform, click on the Anchor Presets square icon, which will result in the appearance of several rows and columns of preset position squares. Hold down SHIFT and ALT and click on the top and column center rows.

  6. Create a folder named Scripts and create a C# script class called ClockDigital in this new folder:

    using UnityEngine;
    using System.Collections;
    
    using UnityEngine.UI;
    using System;
    
    public class ClockDigital : MonoBehaviour {
      private Text textClock;
    
      void Start (){
        textClock = GetComponent<Text>();
      }
    
      void Update (){
        DateTime time = DateTime.Now;
        string hour = LeadingZero( time.Hour );
        string minute = LeadingZero( time.Minute );
        string second = LeadingZero( time.Second );
    
        textClock.text = hour + ":" + minute + ":" + second;
      }
    
      string LeadingZero (int n){
        return n.ToString().PadLeft(2, '0');
      }
    }
  7. With GameObject Text-clock selected in the Hierarchy panel, drag your ClockDigital script onto it to add an instance of this script class as a component to GameObject Text-clock, as shown in the following screenshot:

  8. When you run the scene, you will now see a digital clock, showing hours, minutes, and seconds, at the top-center part of the screen.

How it works...

You added a Text GameObject to a scene. You have added an instance of the ClockDigital C# script class to that GameObject.

Notice that as well as the standard two C# packages (UnityEngine and System.Collections) that are written by default for every new script, you have added the using statements for two more C# script packages, UnityEngine.UI and System. The UI package is needed, since our code uses UI Text object; and the System package is needed, since it contains the DateTime class that we need to access the clock on the computer where our game is running.

There is one variable, textClock, which will be a reference to the Text component, whose text content we wish to update in each frame with the current time in hours, minutes, and seconds.

The Start() method (executed when the scene begins) sets the textClock variable to be a reference to the Text component in the GameObject, to which our scripted object has been added.

Note

Note that an alternative approach would be to make textClock a public variable. This will allow us to assign it via drag-and-drop in the Inspector panel.

The Update()method is executed in every frame. The current time is stored in the time variable, and strings are created by adding leading zeros to the number values for the hours, minutes, and seconds properties of variable time.

This method finally updates the text property (that is, the letters and numbers that the user sees) to be a string, concatenating the hours, minutes, and seconds with colon separator characters.

The LeadingZero(…)method takes as input an integer and returns a string of this number with leading zeros added to the left, if the value was less than 10.

There's more...

There are some details that you don't want to miss.

The Unity tutorial for animating an analogue clock

Unity has published a nice tutorial on how to create 3D objects, and animate them through C# script to display an analogue clock at https://unity3d.com/learn/tutorials/modules/beginner/scripting/simple-clock.

 

Displaying a digital countdown timer


This recipe will show you how to display a digital countdown clock shown here:

Getting ready

This recipe adapts the previous one. So, make a copy of the project for the previous recipe, and work on this copy.

For this recipe, we have prepared the script that you need in a folder named Scripts in the 1362_01_03 folder.

How to do it...

To create a digital countdown timer, follow these steps:

  1. In the Inspector panel, remove the scripted component, ClockDigital, from GameObject Text-clock.

  2. Create a DigitalCountdown C# script class containing the following code, and add an instance as a scripted component to GameObject Text-clock:

    using UnityEngine;
    using System.Collections;
    using UnityEngine.UI;
    using System;
    
    public class DigitalCountdown : MonoBehaviour {
      private Text textClock;
    
      private float countdownTimerDuration;
      private float countdownTimerStartTime;
    
      void Start (){
        textClock = GetComponent<Text>();
        CountdownTimerReset(30);
      }
    
      void Update (){
        // default - timer finished
        string timerMessage = "countdown has finished";
        int timeLeft = (int)CountdownTimerSecondsRemaining();
    
        if(timeLeft > 0)
          timerMessage = "Countdown seconds remaining = " + LeadingZero( timeLeft );
    
        textClock.text = timerMessage;
      }
    
      private void CountdownTimerReset (float delayInSeconds){
        countdownTimerDuration = delayInSeconds;
        countdownTimerStartTime = Time.time;
      }
    
      private float CountdownTimerSecondsRemaining (){
        float elapsedSeconds = Time.time - countdownTimerStartTime;
        float timeLeft = countdownTimerDuration - elapsedSeconds;
        return timeLeft;
      }
    
      private string LeadingZero (int n){
        return n.ToString().PadLeft(2, '0');
      }
    }
  3. When you run the scene, you will now see a digital clock counting down from 30. When the countdown reaches zero, the message countdown has finished will be displayed.

How it works...

You added a Text GameObject to a scene. You have added an instance of the DigitalCountdown C# script class to that GameObject.

There is one variable, textClock, which will be a reference to the Text component, whose text content we wish to update in each frame with a time remaining message (or a timer complete message). Then, a call is made to the CountdownTimerReset(…) method, passing an initial value of 30 seconds.

The Start() method (executed when the scene begins) sets the textClock variable to find the Text component in the GameObject where our scripted object has been added.

The Update() method is executed in every frame. This method initially sets the timerMessage variable to a message, stating that the timer has finished (the default message to display). Then the seconds remaining are tested to be greater than zero. And if so, then the message variable has its contents changed to display the integer (whole) number of the seconds remaining in the countdown—retrieved from the CountdownTimerSecondsRemaining() method. This method finally updates the text property (that is, the letters and numbers that the user sees) to be a string with a message about the remaining seconds.

The CountdownTimerReset(…) method records the number of seconds provided, and the time the method was called.

The CountdownTimerSecondsRemaining() method returns an integer value of the number of seconds remaining.

 

Creating a message that fades away


Sometimes, we want a message to display just for a certain time, and then fade away and disappear, which will appear as shown in this screenshot:

Getting ready

This recipe adapts the first recipe in this chapter, so make a copy of that project to work on for this recipe.

For this recipe, we have prepared the script that you need in a folder named Scripts in the 1362_01_04 folder.

How to do it...

To display a text message that fades away, follow these steps:

  1. Import the provided C# script class called CountdownTimer.

  2. Ensure that GameObject Text-hello is selected in the Hierarchy tab. Then, attach an instance of the CountdownTimer C# script class as a component of this GameObject.

  3. Create a C# script class, FadeAway, containing the following code, and add an instance as a scripted component to the GameObject Text-hello:

    using UnityEngine;
    using System.Collections;
    using UnityEngine.UI;
    
    public class FadeAway : MonoBehaviour {
      private CountdownTimer countdownTimer;
      private Text textUI;
      private int fadeDuration = 5;
      private bool fading = false;
    
      void Start (){
        textUI = GetComponent<Text>();
        countdownTimer = GetComponent<CountdownTimer>();
    
        StartFading(fadeDuration);
      }
    
      void Update () {
        if(fading){
          float alphaRemaining = countdownTimer.GetProportionTimeRemaining();
          print (alphaRemaining);
          Color c = textUI.material.color;
          c.a = alphaRemaining;
          textUI.material.color = c;
    
          // stop fading when very small number
          if(alphaRemaining < 0.01)
            fading = false;
        }
      }
    
      public void StartFading (int timerTotal){
        countdownTimer.ResetTimer(timerTotal);
        fading = true;
      }
    }
  4. When you run the scene, you will now see that the message on the screen slowly fades away, disappearing after 5 seconds.

How it works...

An instance of the provided CountdownTimer script class was added as a component to the GameObject Text-hello.

You added to the GameObject Text-hello an instance of the scripted class, FadeAway. The Start()method caches references to the Text and CountdownTimer components in the countdownTimer and textUI variables. Then, it calls the StartFading(…)method, passing in the number 5, so that the message will have faded to invisible after 5 seconds.

The StartFading(…) method starts this timer scripted component to countdown to the given number of seconds. It also sets the fading Boolean flag variable to true.

The Update() method, in each frame, tests if the fading variable is true. If it is true, then the alpha (transparency) component of the color of the Text-hello object is set to a value between 0.0 and 1.0, based on the proportion of the time remaining in the CountdownTimer object. Finally, if the proportion of time remaining is less than a very small value (0.01), then the fading variable is set to false (to save the processing work since the text is now invisible).

 

Displaying a perspective 3D text message


Unity provides an alternative way to display text in 3D via the TextMesh component. While this is really suitable for a text-in-the-scene kind of situation (such as billboards, road signs, and generally wording on the side of 3D objects that might be seen close up), it is quick to create, and is another way of creating interesting menus or instructions scenes, and the like.

In this recipe, you'll learn how to create a scrolling 3D text, simulating the famous opening credits of the movie Star Wars, which looks something like this:

Getting ready

For this recipe, we have prepared the fonts that you need in a folder named Fonts, and the text file that you need in a folder named Text, in the 1362_01_04 folder.

How to do it...

To display perspective 3D text, follow these steps:

  1. Create a new Unity 3D project (this ensures that we start off with a Perspective camera, suitable for the 3D effect that we want to create).

    Note

    If you need to mix 2D and 3D scenes in your project, you can always manually set any camera's Camera Projection property to Perspective or Orthographic via the Inspector panel.

  2. In the Hierarchy panel, select the Main Camera item, and, in the Inspector panel, set its properties as follows: Camera Clear Flags to solid color, Field of View to 150. Also set the Background color to black.

  3. Import the provided Fonts folder.

  4. In the Hierarchy panel, add a UI | Text game object to the scene – choose menu: GameObject | UI | Text. Name this GameObject as Text-star-wars. Set its Text Content as Star Wars (with each word on a new line). Then, set its Font to Xolonium Bold, and its Font Size to 50. Use the anchor presets in Rect Transform to position this UI Text object at the top center of the screen.

  5. In the Hierarchy panel, add a 3D Text game object to the scene – choose menu: GameObject | 3D Object | 3D Text. Name this GameObject Text-crawler.

  6. In the Inspector panel, set the Transform properties for GameObject Text-crawler as follows: Position (0, -300, -20), Rotation (15, 0, 0).

  7. In the Inspector panel, set the Text Mesh properties for GameObject Text-crawler as follows:

    • Paste the content of the provided text file, star_wars.txt, into Text.

    • Set Offset Z = 20, Line Spacing = 0.8, and Anchor = Middle center

    • Set Font Size = 200, Font = SourceSansPro-BoldIt

  8. When the scene is made to run, the Star Wars story text will now appear nicely squashed in 3D perspective on the screen.

How it works...

You have simulated the opening screen of the movie Star Wars, with a flat UI Text object title at the top of the screen, and 3D Text Mesh with settings that appear to be disappearing into the horizon with 3D perspective 'squashing'.

There's more...

There are some details that you don't want to miss.

We have to make this text crawl like it does in the movie

With a few lines of code, we can make this text scroll in the horizon just as it does in the movie. Add the following C# script class, ScrollZ, as a component to GameObject Text-crawler:

using UnityEngine;
using System.Collections;

public class ScrollZ : MonoBehaviour {
  public float scrollSpeed = 20;

  void Update () {
    Vector3 pos = transform.position;
    Vector3 localVectorUp = transform.TransformDirection(0,1,0);
    pos += localVectorUp * scrollSpeed * Time.deltaTime;
    transform.position = pos;
  }
}

In each frame via the Update() method, the position of the 3D text object is moved in the direction of this GameObject's local up-direction.

Where to learn more

Learn more about 3D Text and Text Meshes in the Unity online manual at http://docs.unity3d.com/Manual/class-TextMesh.html.

Note

NOTE: An alternative way of achieving perspective text like this would be to use a Canvas with render mode World Space.

 

Displaying an image


There are many cases where we wish to display an image onscreen, including logos, maps, icons, splash graphics, and so on. In this recipe, we will display an image at the top of the screen, and make it stretch to fit whatever width that the screen is resized to.

The following screenshot shows Unity displaying an image:

Getting ready

For this recipe, we have prepared the image that you need in a folder named Images in the 1362_01_06 folder.

How to do it...

To display a stretched image, follow these steps:

  1. Create a new Unity 3D project.

    Note

    3D projects will, by default, import images as a Texture, and 2D projects will import images as Sprite (2D and UI). Since we're going to use a RawImage UI component, we need our images to be imported as textures.

  2. Set the Game panel to a 400 x 300 size. Do this via menu: Edit | Project Settings | Player. Ensure that the Resolution | Default is Full Screen setting check is unchecked, and the width/height is set to 400 x 300. Then, in the Game panel, select Stand Alone (400 x 300). This will allow us to test the stretching of our image to a width of 400 pixels.

  3. Import the provided folder, which is called Images. In the Inspector tab, ensure that the unity5_learn image has Texture Type set to Texture. If it does not, then choose Texture from the drop-down list, and click on the Apply button. The following screenshot shows the Inspector tab with the Texture settings:

  4. In the Hierarchy panel, add a UI | RawImage GameObject to the scene named RawImage-unity5.

    Note

    If you wish to prevent the distortion and stretching of an image, then use the UI Sprite GameObject instead, and ensure that you check the Preserve Aspect option, in its Image (Script) component, in the Inspector panel.

  5. Ensure that the GameObject RawImage-unity5 is selected in the Hierarchy panel. From your Project folder (Images), drag the unity5_learn image into the Raw Image (Script) public property Texture. Click on the Set Native Size button to preview the image before it gets stretched, as shown:

  6. Now, in Rect Transform, click on the Anchor Presets square icon, which will result in several rows and columns of preset position squares appearing. Hold down SHIFT and ALT and click on the top row and the stretch column.

  7. The image will now be positioned neatly at the top of the Game panel, and will be stretched to the full width of 400 pixels.

How it works...

You have ensured that an image has Texture Type set to Texture. You added a UI RawImage control to the scene. The RawImage control has been made to display the unity5_learn image file.

The image has been positioned at the top of the Game panel, and using the anchor and pivot presets, it has made the image stretch to fill the whole width, which we set to 400 pixels via the Player settings.

There's more...

There are some details that you don't want to miss:

Working with Sprites and UI Image components

If you simply wish to display non-animated images, then Texture images and UI RawImage controls are the way to go. However, if you want more options on how an image should be displayed (such as tiling, and animation), then the UI Sprite control should be used instead. This control needs image files to be imported as the Sprite (2D and UI) type.

Once an image file has been dragged into the UI Image control's Sprite property, additional properties will be available, such as Image Type, options to preserve aspect ratio, and so on.

See also

An example of tiling a Sprite image can be found in the Revealing icons for multiple object pickups by changing the size of a tiled image recipe in Chapter 2, Inventory GUIs.

 

Creating UI Buttons to move between scenes


As well as scenes where the player plays the game, most games will have menu screens, which display to the user messages about instructions, high scores, the level they have reached so far, and so on. Unity provides the UI Buttons to make it easy to offer users a simple way to indicate their choice of action on such screens.

In this recipe, we'll create a very simple game consisting of two screens, each with a button to load the other one, similar to the following screenshot:

How to do it...

To create a button-navigable multi-scene game, follow these steps:

  1. Create a new Unity 2D project.

  2. Save the current (empty) scene, naming it page1.

  3. Add a UI Text object positioned at the top center of the scene, containing text Main Menu / (page 1) in a large font size.

  4. Add a UI Button to the scene positioned in the middle center of the screen. In the Hierarchy panel, click on the show children triangle to display the UI Text child of this button GameObject. Select the Text button-child GameObject, and in the Inspector panel for the Text property of the Text (Script) component, enter the button text called goto page 2, as shown here:

  5. Add the current scene to the build, choosing menu: File | Build Settings…. Then, click on the Add Current button so that the page1 scene becomes the first scene on the list of Scenes in the Build.

    Note

    We cannot tell Unity to load a scene that has not been added to the list of scenes in the build. We use the Application.LoadLevel(…)code to tell Unity to load the scene name (or numeric index) that is provided.

  6. Create a C# script class, MenuActions, containing the following code, and add an instance as a scripted component to the Main Camera:

    using UnityEngine;
    using System.Collections;
    
    public class MenuActions : MonoBehaviour {
      public void MENU_ACTION_GotoPage(string sceneName){
        Application.LoadLevel(sceneName);
      }
    }
  7. Ensure that the Button is selected in the Hierarchy and click on the plus sign "+" button at the bottom of the Button (Script) component, in the Inspector view, to create a new OnClick event handler for this button.

  8. Drag the Main Camera from the Hierarchy over the Object slot—immediately below the menu saying Runtime Only. This means that when the Button receives an OnClick event, we can call a public method from a scripted object inside the Main Camera.

  9. Now, select the MENU_ACTION_GotoPage() method from the MenuActions drop-down list (initially showing No Function). Type page2 (the name of the scene we want to be loaded when this button is clicked) in the text box, below the method's drop-down menu. This page2 string will be passed to the method when the button receives an OnClick event message, as shown here:

  10. Save the current scene, create a new empty scene, and then save this new scene as page2.

  11. Follow the similar steps for this scene. Add a UI Text GameObject, displaying the text Instructions / (page 2) in a large font size. Add a UI Button, showing the goto page 1 text.

  12. Add the current scene to the build (so now, both page1 and page2 will be listed in the build).

  13. Add an instance of MenuActions script class to the Main Camera.

  14. Select the Button in the Hierarchy panel, and add an On Click event handler, which will pass the MENU_ACTION_GotoPage() method the string page1 (the name of the scene we want to be loaded when this button is clicked).

  15. Save the scene.

  16. When you run the page1 scene, you will be presented with your Main Menu text and a button, which when clicked, makes the game load the page2 scene. On scene page2, you'll have a button to take you back to page1.

How it works...

You have created two scenes, and added both of them to the game build. Each scene has a button, which when clicked (when the game is playing), makes Unity load the (named) other scene. This is made possible because when each button is clicked, it runs the MENU_ACTION_GotoPage(…)method from the scripted MenuActions component inside the Main Camera. This method inputs a text string of the name of the scene to be loaded, so that the button in the page1 scene gives the string name of page2 as the scene to be loaded, and vice versa.

When a UI Button is added to the Hierarchy panel, a child UI Text object is also automatically created, and the content of the Text property of this UI Text child is the text that the user sees on the button.

There's more...

There are some details that you don't want to miss.

Visual animation for the button mouse-over

There are several ways in which we can visually inform the user that the button is interactive when they move their mouse cursor over it. The simplest is to add a color tint that will appear when the mouse is over the button—this is the default Transition. With the Button selected in the Hierarchy, choose a tint color (for example, red), for the Highlighted Color property of the Button (Script) component, in the Inspector tab, as shown here:

Another form of visual Transition to inform the user of an active button is Sprite Swap. In this case, properties for different images for Targeted/Highlighted/Pressed/Disabled are available in the Inspector tab. The default Targeted Graphic is the built-in Unity Button (image) – this is the grey rounded rectangle default when GameObjects buttons are created. Dragging in a very different-looking image for the Highlighted Sprite is an effective alternative to set a color hint. We have provided a rainbow.png image with the project for this recipe that can be used for the Button mouse over Highlighted Sprite. The following screenshot shows the button with this rainbow background image:

Animating button properties on mouse over

Finally, animations can be created for dynamically highlighting a button to the user, for example, a button might get larger when the mouse is over it, and then it might shrink back to its original size when the mouse pointer is moved away. These effects are achieved by choosing the Animation option for the Transition property, and by creating an animation controller with triggers for the Normal, Highlighted, Pressed and Disabled states. To animate a button for enlargement when the mouse is over it (the highlighted state), do the following:

  1. Create a new Unity 2D project.

  2. Create a button.

  3. In the Inspector Button (Script) component, set the Transition property to Animation.

  4. Click the Auto Generate Animation button (just below the Disabled Trigger property) for the Button (Script) component, as shown here:

  5. Save the new controller by naming it button-animation-controller.

  6. Ensure that the Button GameObject is selected in the Hierarchy. Then, in the Animation panel, select the Highlighted clip from the drop-down menu, as shown here:

  7. In the Animation panel, click on the red record circle button, and then click on the Add Property button, choosing to record changes to the Rect Transform | Scale property.

  8. Two key frames will have been created, delete the second one at 1:00 (since we don't want a "bouncing" button), as shown in the following screenshot .

  9. Select the first key frame at 0:00 (the only one now!). Then, in the Inspector view, set the X and Y scale properties of the Rect Transform component to (1.2, 1.2).

  10. Finally, click on the red record circle button for the second time to end the recording of the animation changes.

  11. Save and run your scene, and you will see that the button smoothly animates to get larger when the mouse is over it, and then smoothly returns to its original size when the mouse is moved away.

The following web pages offer video and web-based tutorials on UI animations:

 

Organizing images inside panels and changing panel depths via buttons


UI Panels are provided by Unity to allow UI controls to be grouped and moved together, and also to visually group elements with an Image background (if desired). The sibling depth is what determines which UI elements will appear above or below others. We can see the sibling depth explicitly in the Hierarchy, since the top-to-bottom sequence of UI GameObjects in the Hierarchy sets the sibling depth. So, the first item has a depth of 1, the second has a depth of 2, and so on. The UI GameObjects with larger sibling depths (further down the Hierarchy) appear above the UI GameObjects with lower sibling depths.

In this recipe, we'll create three UI panels, each showing a different playing card image. We'll also add four triangle arrangement buttons to change the display order (move to bottom, move to top, move up one, and move down one).

Getting ready

For this recipe, we have prepared the images that you need in a folder named Images in the 1362_01_08 folder.

How to do it...

To create the UI Panels whose layering can be changed by the user-clicking buttons, follow these steps:

  1. Create a new Unity 2D project.

  2. Create a new UI Panel named Panel-jack-diamonds. Position it in the middle-center part of the screen, and size it 200 pixels wide by 300 pixels high. Uncheck the Image (Script) component for this panel (since we don't want to see the default semi-transparent rectangular grey background image of a panel).

  3. Create a new UI Image, and child this image to Panel-jack-diamonds.

  4. Position the Panel-jack-diamonds image at center-middle, and size it to 200 x 300. Drag the Jack-of-diamonds playing card image into the Source Image property, for the Image (Script) component in the Inspector tab.

  5. Create a UI Button named Button-move-to-front. Child this button to Panel-jack-diamonds. Delete the Text child GameObject of this button (since we'll use an icon to indicate what this button does).

  6. Size the Button-move-to-front button to 16 x 16, and position it top-center of the player card image, so that it can be seen at the top of the playing card. Drag the icon_move_to_front arrangement triangle icon image into the Source Image property, for the Image (Script) component, in the Inspector view.

  7. Ensure that the Button-move-to-front button is selected in the Hierarchy. Then, click on the plus sign (+) at the bottom of the Button (Script) component, in the Inspector view to create a new OnClick event handler for this button.

  8. Drag Panel-jack-diamonds from the Hierarchy over the Object slot (immediately below the menu saying Runtime Only).

  9. Now, select the RectTransform.SetAsLastSibling method from the drop-down function list (initially showing No Function).

    Note

    This means that when the Button receives an OnClick event, the RectTransform of the Panel will be sent the SetAsLastSibling message – this will move the Panel to the bottom of the GameObjects in the Canvas, and therefore will move this Panel in front of all other GameObjects in the Canvas.

  10. Repeat step 2; create a second Panel with a move-to-front button. Name this second Panel Panel-2-diamonds, then move and position it slightly to the right of Panel-jack-diamonds, allowing both the move-to-front buttons to be seen.

  11. Save your scene and run the game. You will be able to click the move-to-front button on either of the cards to move that card's panel to the front. If you run the game with the Game panel not maximized, you'll actually see the panels changing order in the list of the children of the Canvas in the Hierarchy.

How it works...

You've created two UI Panels, each panel containing an image of a playing card and a button whose action will make its parent panel move to the front. The button's action illustrates how the OnClick function does not have to be the calling of a public method of a scripted component of an object, but it can be sending a message to one of the components of the targeted GameObject—in this instance we send the SetAsLastSibling message to the RectTransform of the Panel in which the Button is located.

There's more...

There are some details that you don't want to miss.

Moving up or down by just one position, using scripted methods

While the Rect Transform offers a useful SetAsLastSibling (move to front) and SetAsFirstSibling (move to back), and even SetSiblingIndex (if we knew exactly what position in the sequence to type in), there isn't a built-in way to make an element move up or down, just a single position in the sequence of GameObjects in the Hierarchy panel. However, we can write two straightforward methods in C# to do this, and we can add buttons to call these methods, providing full control of the top-to-bottom arrangement of the UI controls on the screen. To implement four buttons (move-to-front/move-to-back/up one/down one), do the following:

  1. Create a C# script class called ArrangeActions, containing the following code, and add an instance as a scripted component to each of your Panels:

    using UnityEngine;
    using UnityEngine.UI;
    using UnityEngine.EventSystems;
    using System.Collections;
    
    public class ArrangeActions : MonoBehaviour {
      private RectTransform panelRectTransform;
    
      void Start(){
        panelRectTransform = GetComponent<RectTransform>();
      }
    
      public void MoveDownOne(){
        print ("(before change) " + GameObject.name +  " sibling index = " + panelRectTransform.GetSiblingIndex());
    
        int currentSiblingIndex = panelRectTransform.GetSiblingIndex();
        panelRectTransform.SetSiblingIndex( currentSiblingIndex - 1 );
    
        print ("(after change) " + GameObject.name +  " sibling index = " + panelRectTransform.GetSiblingIndex());
      }
    
      public void MoveUpOne(){
        print ("(before change) " + GameObject.name +  " sibling index = " + panelRectTransform.GetSiblingIndex());
    
        int currentSiblingIndex = panelRectTransform.GetSiblingIndex();
        panelRectTransform.SetSiblingIndex( currentSiblingIndex + 1 );
    
        print ("(after change) " + GameObject.name +  " sibling index = " + panelRectTransform.GetSiblingIndex());
      }
    }
  2. Add a second button to each card panel, this time, using the arrangement triangle icon image called icon_move_to_front, and set the OnClick event function for these buttons to SetAsFirstSibling.

  3. Add two further buttons to each card panel with the up and down triangle icon images: icon_down_one and icon_up_one. Set the OnClick event handler function for the down-one buttons to call the MoveDownOne() method, and set the functions for the up-one buttons to call the MoveUpOne() method.

  4. Copy one of the panels to create a third card (this time showing the Ace of diamonds). Arrange the three cards so that you can see all four buttons for at least two of the cards, even when those cards are at the bottom (see the screenshot at the beginning of this recipe).

  5. Save the scene and run your game. You will now have full control over the layering of the three card panels.

 

Displaying the value of an interactive UI Slider


This recipe illustrates how to create an interactive UI Slider, and execute a C# method each time the user changes the Slider value.

How to do it...

To create a UI Slider and display its value on the screen, follow these steps:

  1. Create a new 2D project.

  2. Add a UI Text GameObject to the scene with a Font size of 30 and placeholder text such as slider value here (this text will be replaced with the slider value when the scene starts).

  3. In the Hierarchy panel, add a UI | Slider game object to the scene—choose the menu: GameObject | UI | Slider.

  4. In the Inspector tab, modify settings for the Rect Transform to position the slider on the top-middle part of the screen and the text just below it.

  5. In the Inspector tab, set the Min Value of the slider to 0, the Max Value to 20, and check the Whole Numbers checkbox, as shown here:

  6. Create a C# script class called SliderValueToText, containing the following code, and add an instance as a scripted component to the GameObject called Text:

    using UnityEngine;
    using System.Collections;
    using UnityEngine.UI;
    
    public class SliderValueToText : MonoBehaviour {
      public Slider sliderUI;
      private Text textSliderValue;
    
      void Start (){
        textSliderValue = GetComponent<Text>();
        ShowSliderValue();
      }
    
      public void ShowSliderValue () {
        string sliderMessage = "Slider value = " + sliderUI.value;
        textSliderValue.text = sliderMessage;
      }
    }
  7. Ensure that the Text GameObject is selected in the Hierarchy. Then, in the Inspector view, drag the Slider GameObject into the public Slider UI variable slot for the Slider Value To Text (Script) scripted component, as shown here:

  8. Ensure that the Slider GameObject is selected in the Hierarchy. Then, in the Inspector view, drag the Text GameObject into the public None (Object) slot for the Slider (Script) scripted component, in the section for On Value Changed (Single).

    Note

    You have now told Unity to which object a message should be sent each time the slider is changed.

  9. From the drop-down menu, select SliderValueToText and the ShowSliderValue() method, as shown in the following screenshot. This means that each time the slider is updated, the ShowSliderValue()method, in the scripted object, in GameObject Text will be executed.

  10. When you run the scene, you will now see a slider. Below it, you will see a text message in the Slider value = <n> form.

  11. Each time the slider is moved, the text value shown will be (almost) instantly updated. The values should range from 0 (the leftmost of the slider) to 20 (the rightmost of the slider).

    Note

    The update of the text value on the screen probably won't be instantaneous, as in happening in the same frame as the slider value is moved, since there is some computation involved in the slider deciding that an On Value Changed event message needs to be triggered, and then looking up any methods of objects that are registered as event handlers for such an event. Then, the statements in the object's method need to be executed in sequence. However, this should all happen within a few milliseconds, and should be sufficiently fast enough to offer the user a satisifyingly responsive UI for interface actions such as changing and moving this slider.

How it works...

You have added to the Text GameObject a scripted instance of the SliderValueToText class.

The Start() method, which is executed when the scene first runs, sets the variable to be a reference to the Text component inside the Slider item. Next, the ShowSliderValue() method is called, so that the display is correct when the scene begins (the initial slider value is displayed).

This contains the ShowSliderValue() method, which gets the value of the slider. It updates the text displayed to be a message in the form: Slider value = <n>.

You created a UI Slider GameObject, and set it to be whole numbers in the 0-20 range.

You added to the UI Slider GameObject's list of On Value Changed event listeners the ShowSliderValue() method of the SliderValueToText scripted component. So, each time the slider value changes, it sends a message to call the ShowSliderValue() method, and so the new value is updated on the screen.

 

Displaying a countdown timer graphically with a UI Slider


There are many cases where we wish to inform the player of the proportion of time remaining, or at the completion of some value at a point in time, for example, a loading progress bar, the time or health remaining compared to the starting maximum, how much the player has filled up their water bottle from the fountain of youth, and so on. In this recipe, we'll illustrate how to remove the interactive 'handle' of a UI Slider, and change the size and color of its components to provide us with an easy-to-use, general purpose progress/proportion bar. In this recipe, we'll use our modified slider to graphically present to the user how much time remains for a countdown timer.

Getting ready

This recipe adapts the previous one. So, make a copy of the project for the previous recipe, and work on this copy to follow this recipe.

For this recipe, we have prepared the script and images that you need in the folders named Scripts and Images in the 1362_01_10 folder.

How to do it...

To create a digital countdown timer with a graphical display, follow these steps:

  1. Delete the Text GameObject.

  2. Import the CountdownTimer script and the red_square and green_square images to this project.

  3. Ensure that the Slider GameObject is selected in the Hierarchy tab.

  4. Deactivate the Handle Slide Area child GameObject (by unchecking it)

  5. You'll see the "drag circle" disappear in the Game panel (the user will not be dragging the slider, since we want this slider to be display-only), as shown in the following screenshot:

  6. Select the Background child:

    • Drag the red_square image into the Source Image property of the Image (Script) component in the Inspector view

  7. Select the Fill child:

    • Drag the green_square image into the Source Image property of the Image (Script) component in the Inspector tab

  8. Select the Fill Area child:

    • In the Rect Transform component, use the Anchors preset position of left-middle

    • Set Width to 155 and Height to 12, as shown here:

  9. Ensure that the Slider GameObject is selected in the Hierarchy. Then, attach an instance of C# script class called CountdownTimer as a component of this GameObject.

  10. Create a C# script class called SliderTimerDisplay containing the following code, and add an instance as a scripted component to the Slider GameObject:

    using UnityEngine;
    using System.Collections;
    using UnityEngine.UI;
    
    public class SliderTimerDisplay : MonoBehaviour {
      private CountdownTimer countdownTimer;
      private Slider sliderUI;
      private int startSeconds = 30;
    
      void Start (){
        SetupSlider();
        SetupTimer();
      }
    
      void Update () {
        sliderUI.value = countdownTimer.GetProportionTimeRemaining();
        print (countdownTimer.GetProportionTimeRemaining());
      }
    
      private void SetupSlider (){
        sliderUI = GetComponent<Slider>();
        sliderUI.minValue = 0;
        sliderUI.maxValue = 1;
        sliderUI.wholeNumbers = false;
      }
    
      private void SetupTimer (){
        countdownTimer = GetComponent<CountdownTimer>();
        countdownTimer.ResetTimer(startSeconds);
      }
    }
  11. Run your game and you will see the slider move with each second, revealing more and more of the red background to indicate the time remaining.

How it works...

You hid the Handle Slide Area child so that Slider is for display only, and cannot be interacted with by the user. The Background color of the Slider was set to red, so that, as the counter goes down, more and more red is revealed—warning the user that the time is running out. The Fill of the Slider was set to green, so that the proportion remaining is displayed in green (the more green it becomes, the larger the value of the slider/timer).

An instance of the provided CountdownTimer script class was added as a component to the Slider. The ResetTimer(…) method records the number of seconds provided and the time the method was called. The GetProportionRemaining() method returns a value from 0.0-1.0, representing the proportion of the seconds remaining (1.0 being all seconds, 0.5 half the seconds, and 0.0 meaning that no seconds are left).

You have added to the Slider GameObject an instance of the SliderTimerDisplay scripted class. The Start() method calls the SetupSlider() and SetupTimer() methods.

The SetupSlider() method sets the sliderUI variable to be a reference to the Slider component, and sets up this slider mapped to float (decimal) values between 0.0 and 1.0.

The SetupTimer() method sets the countdownTimer variable to be a reference for the CountdownTimer component, and starts this timer scripted component to count down from 30 seconds.

In each frame, the Update()method sets the slider value to the float returned by calling the GetProportionRemaining()method from the running timer.

Note

Try to work with floats between 0.0-1.0 whenever possible.

Integers could have been used, setting the Slider min to 0 and max to 30 (for 30 seconds). However, changing the total number of seconds would then also require the Slider settings to be changed. In most cases working with a float proportion between 0.0 and 1.0 is the more general-purpose and reusable approach to adopt.

 

Displaying a radar to indicate the relative locations of objects


A radar displays the locations of other objects relative to the player, usually based on a circular display, where the center represents the player, and each graphical 'blip' indicates how far away and what relative direction objects are to the player. Sophisticated radar displays will display different categories of objects with different colored or shaped 'blip' icons.

In the screenshot, we can see 2 red square 'blips', indicating the relative position of the 2 red cube GameObjects tagged Cube near the player, and a yellow circle 'blip' indicating the relative position of the yellow sphere GameObject tagged Sphere. The green circle radar background image gives the impression of an aircraft control tower radar or something similar.

Getting ready

For this recipe, we have prepared the images that you need in a folder named Images in 1362_01_11.

How to do it...

To create a radar to show the relative positions of the objects, follow these steps:

  1. Create a new 3D project by importing the following standard assets:

    • Environment

    • Characters

    • Cameras

  2. Create a terrain by navigating to the Create | 3D Object | Terrain menu.

  3. Size the terrain 20 x 20, positioned at (-10, 0, -10)—so that its center is at (0, 0, 0), as shown in the following figure:

  4. Texture paint your terrain with the SandAlbedo option, as shown here:

  5. From the Standard Assets folder in the Project panel, drag the prefab ThirdPersonController into the scene and position it at (0, 1, 0).

  6. Tag this ThirdPersonController GameObject called Player.

  7. Remove the Main Camera GameObject.

  8. From the Standard Assets folder in the Project panel, drag the prefab Multi-PurposeCameraRig into the scene.

  9. With Multi-PurposeCameraRig selected in the Hierarchy, drag the ThirdPersonController GameObject into the Target property of the Auto Cam (Script) public variable in the Inspector tab, as shown in the following screenshot:

  10. Import the provided folder known as Images.

  11. In the Hierarchy panel, add a UI | RawImage GameObject to the scene named RawImage-radar.

  12. Ensure that the RawImage-radar GameObject is selected in the Hierarchy panel. From your Project Images folder, drag the radarBackground image into the Raw Image (Script) public property Texture.

  13. Now, in Rect Transform position RawImage-radar at the top-left part using the Anchor Presets item. Then set the width and height to 200 pixels.

  14. Create another new UI RawImage named RawImage-blip. Assign the yellowCircleBlackBorder texture. Tag the Blip GameObject.

  15. In the Project panel, create a new empty prefab named blip-sphere, and drag the RawImage-blip GameObject into this prefab to store all its properties.

  16. Now, change the texture of RawImage-blip to redSquareBlackBorder.

  17. In the Project panel, create a new empty prefab named blip-cube, and drag the RawImage-blip GameObject into this prefab to store all its properties.

  18. Delete the RawImage-blip GameObject from the Hierarchy panel.

  19. Create a C# script class called Radar, containing the following code, and add an instance as a scripted component to the RawImage-radar GameObject:

    using UnityEngine;
    using System.Collections;
    using UnityEngine.UI;
    
    public class Radar : MonoBehaviour{
      public float insideRadarDistance = 20;
      public float blipSizePercentage = 5;
    
      public GameObject rawImageBlipCube;
      public GameObject rawImageBlipSphere;
    
      private RawImage rawImageRadarBackground;
      private Transform playerTransform;
      private float radarWidth;
      private float radarHeight;
      private float blipHeight;
      private float blipWidth;
    
      void Start (){
        playerTransform = GameObject.FindGameObjectWithTag("Player").transform;
        rawImageRadarBackground = GetComponent<RawImage>();
    
        radarWidth = rawImageRadarBackground.rectTransform.rect.width;
        radarHeight = rawImageRadarBackground.rectTransform.rect.height;
    
        blipHeight = radarHeight * blipSizePercentage/100;
        blipWidth = radarWidth * blipSizePercentage/100;
      }
    
      void Update (){
        RemoveAllBlips();
        FindAndDisplayBlipsForTag("Cube", rawImageBlipCube);
        FindAndDisplayBlipsForTag("Sphere", rawImageBlipSphere);
      }
    
      private void FindAndDisplayBlipsForTag(string tag, GameObject prefabBlip){
        Vector3 playerPos = playerTransform.position;
        GameObject[] targets = GameObject.FindGameObjectsWithTag(tag);
    
        foreach (GameObject target in targets) {
          Vector3 targetPos = target.transform.position;
          float distanceToTarget = Vector3.Distance(targetPos, playerPos);
          if( (distanceToTarget <= insideRadarDistance) ){
            Vector3 normalisedTargetPosiiton = NormalisedPosition(playerPos, targetPos);
            Vector2 blipPosition = CalculateBlipPosition(normalisedTargetPosiiton);
            DrawBlip(blipPosition, prefabBlip);
          }
        }
      }
    
      private void RemoveAllBlips(){
        GameObject[] blips = GameObject.FindGameObjectsWithTag("Blip");
        foreach (GameObject blip in blips)
          Destroy(blip);
      }
    
      private Vector3 NormalisedPosition(Vector3 playerPos, Vector3 targetPos){
      float normalisedyTargetX = (targetPos.x - playerPos.x)/insideRadarDistance;
        float normalisedyTargetZ = (targetPos.z - playerPos.z)/insideRadarDistance;
        return new Vector3(normalisedyTargetX, 0, normalisedyTargetZ);
      }
    
      private Vector2 CalculateBlipPosition(Vector3 targetPos){
        // find angle from player to target
        float angleToTarget = Mathf.Atan2(targetPos.x, targetPos.z) * Mathf.Rad2Deg;
    
        // direction player facing
        float anglePlayer = playerTransform.eulerAngles.y;
    
        // subtract player angle, to get relative angle to object
        // subtract 90
        // (so 0 degrees (same direction as player) is UP)
        float angleRadarDegrees =  angleToTarget - anglePlayer - 90;
    
        // calculate (x,y) position given angle and distance
        float normalisedDistanceToTarget = targetPos.magnitude;
        float angleRadians = angleRadarDegrees * Mathf.Deg2Rad;
        float blipX = normalisedDistanceToTarget * Mathf.Cos(angleRadians);
        float blipY = normalisedDistanceToTarget * Mathf.Sin(angleRadians);
    
        // scale blip position according to radar size
        blipX *= radarWidth/2;
        blipY *= radarHeight/2;
    
        // offset blip position relative to radar center
        blipX += radarWidth/2;
        blipY += radarHeight/2;
    
        return new Vector2(blipX, blipY);
      }
    
      private void DrawBlip(Vector2 pos, GameObject blipPrefab){
        GameObject blipGO = (GameObject)Instantiate(blipPrefab);
        blipGO.transform.SetParent(transform.parent);
        RectTransform rt = blipGO.GetComponent<RectTransform>();
        rt.SetInsetAndSizeFromParentEdge(RectTransform.Edge.Left, pos.x, blipWidth);
        rt.SetInsetAndSizeFromParentEdge(RectTransform.Edge.Top, pos.y, blipHeight);
      }
    }
  20. Create two cubes—tagged Cube, textured with a red image called icon32_square_red. Position each away from the player's character.

  21. Create a sphere—tagged Sphere, textured with a red image called icon32_square_yellow. Position this away from the cubes and the player's character.

  22. Run your game. You will see two red squares and one yellow circle on the radar, showing the relative positions of the red cubes and yellow sphere. If you move too far away, then the blips will disappear.

    Note

    This radar script scans 360 degrees all around the player, and only considers straight line distances in the X-Z plane. So, the distances in this radar are not affected by any height difference between the player and target GameObjects. The script can be adapted to ignore targets whose height is more than some threshold different to the player's height. Also, as presented, this recipe radar sees through everything, even if there are obstacles between the player and the target. The recipe can be extended to not show obscured targets through the user of the ray-casting techniques. See the Unity scripting reference for more details about ray-casting at http://docs.unity3d.com/ScriptReference/Physics.Raycast.html.

How it works...

A radar background is displayed on the screen. The center of this circular image represents the position of the player's character. You have created two prefabs; one for red square images to represent each red cube found within the radar distance, and one for yellow circles to represent yellow sphere GameObjects.

The Radar C# script class has been added to the radar UI Image GameObject. This class defines four public variables:

  • insideRadarDistance: This value defines the maximum distance that an object may be from the player to still be included on the radar (objects further than this distance will not be displayed on the radar).

  • blipSizePercentage: This public variable allows the developer to decide how large each 'blip' will be, as a proportion of the radar's image.

  • rawImageBlipCube and rawImageBlipSphere: These are references to the prefab UI RawImages that are to be used to visually indicate the relative distance and position of cubes and spheres on the radar.

Since there is a lot happening in the code for this recipe, each method will be described in its own section.

The Start() method

The Start() method caches a reference to the Transform component of the player's character (tagged as Player). This allows the scripted object to know about the position of the Player's character in each frame. Next, the width and height of the radar image are cached—so, the relative positions for 'blips' can be calculated, based on the size of this background radar image. Finally, the size of each blip (width and height) is calculated, using the blipSizePercentage public variable.

The Update() method

The Update() method calls the RemoveAllBlips() method, which removes any old RawImage UI GameObjects of cubes and spheres that might currently be displayed.

Next, the FindAndDisplayBlipsForTag(…)method is called twice. First, for the objects tagged Cube, to be represented on the radar with the rawImageBlipCube prefab and then again for objects tagged Sphere, to be represented on the radar with the rawImageBlipSphere prefab. As you might expect, most of the hard work for the radar is to be performed by the FindAndDisplayBlipsForTag(…) method.

The FindAndDisplayBlipsForTag(…) method

This method inputs two parameters: the string tag for the objects to be searched for; and a reference to the RawImage prefab to be displayed on the radar for any such tagged objects within the range.

First, the current position of the player's character is retrieved from the cached player transform variable. Next, an array is constructed, referring to all GameObjects in the scene that have the provided tag. This array of GameObjects is looped through, and for each GameObject, the following actions are performed:

  • The position of the target GameObject is retrieved

  • The distance from this target position to the player's position is calculated, and if this distance is within the range (less than or equal to insideRadarDistance), then three steps are now required to get the blip for this object to appear on the radar:

    • The normalized position of the target is calculated by calling NormalisedPosition(…)

    • The position of the blip on the radar is then calculated from this normalized position by calling CalculateBlipPosition(…)

    • Finally, the RawImage blip is displayed by calling DrawBlip(…) and passing the blip position and the reference to the RawImage prefab that is to be created there

The NormalisedPosition(…) method

The NormalisedPosition(…) method inputs the player's character position and the target GameObject position. It has the goal of outputting the relative position of the target to the player, returning a Vector3 object with a triplet of X, Y, and Z values. Note that since the radar is only 2D, we ignore the Yvalue of target GameObjects. So, the Yvalue of the Vector3 object returned by this method will always be 0. So, for example, if a target was at exactly the same location as the player, the returned X, Y, Z Vector3 object would be (0, 0, 0).

Since we know that the target GameObject is no further from the player's character than insideRadarDistance, we can calculate a value in the -1 … 0 … +1 range for the X and Z axis by finding the distance on each axis from the target to the player, and then dividing it by insideRadarDistance. An X value of -1 means that the target is fully to the left of the player (at a distance that is equal to insideRadarDistance), and +1 means it is fully to the right. A value of 0 means that the target has the same X position as the player's character. Likewise, for -1 … 0 … +1 values in the Z-axis (this axis represents how far, in front or behind us an object, is located, which will be mapped to the vertical axis in our radar).

Finally, this method constructs and returns a new Vector3 object, with the calculated X and Z normalized values, and a Y value of zero.

Note

The normalized position

A normalized value is one that has been simplified in some way, so the context has been abstracted away. In this recipe, what we are interested in is where an object is relative to the player. So, our normal form is to get a value of the X and Z position of a target in the -1 to +1 range for each axis. Since we are only considering GameObject within out insideRadarDistance value, we can map these normalized target positions directly onto the location of the radar image in our UI.

The CalculateBlipPosition(…) method

First, we calculate angleToTarget: the angle from (0, 0, 0) to our normalized target position.

Next, we calculate anglePlayer: the angle the player's character is facing. This recipe makes use of the yaw angle of the rotation, which is the rotation about the Y-axis—that is, the direction that a character controller is facing. This can be found in the Y component of a GameObject's eulerAngles component of its transform. You can imagine looking from above and down at the character controller, and see what direction they are facing—this is just what we are trying to display graphically with the compass.

Our desired radar angle (the angleRadarDegrees variable) is calculated by subtracting the player's direction angle from the angle between target and player, since a radar displays the relative angle from the direction that the player is facing, to the target object. In mathematics, an angle of zero indicates an east direction. To correct this, we need to also subtract 90 degrees from the angle.

The angle is then converted into radians, since this is required for the Unity trigonometry methods. We then multiply the Sin() and Cos() results by our normalized distances to calculate the X and Y values respectively (see the following figure):

Our final position values need to be expressed as pixel lengths, relative to the center of the radar. So, we multiply our blipX and blipY values by half the width and the height of the radar; note that we multiply only with half the width, since these values are relative to the center of the radar.

Note

Note: In this figure, alpha is the angle between player and target object, 'a' is the adjacent side, 'h' is the hypotenuse and 'o' is the side opposite the angle.

We then add half the width and height of the radar image to the blipX/Y values. So, these values are now positioned relative to the center.

Finally a new Vector2 object is created and returned, passing back these final calculated X and Y pixel values for the position of our blip icon.

The DrawBlip() method

The DrawBlip() method takes the input parameters of the position of the blip (as a Vector2 X, Y pair), and the reference to the RawImage prefab to be created at that location on the radar.

A new GameObject is created from the prefab, and is parented to the radar GameObject (of which the scripted object is also a component). A reference is retrieved to the Rect Transform of the new RawImage GameObject that has been created for the 'blip'. Calls to the Unity RectTransform method, SetInsetAndSizeFromParentEdge(…), result in the blip GameObject being positioned at the provided horizontal and vertical locations over the radar image, regardless of where in the Game panel the background radar image has been located.

 

Creating UIs with the Fungus open-source dialog system


Rather than constructing your own UI and interactions from scratch each time, there are plenty of UI and dialogue systems available for Unity. One powerful, free, and open source dialog system is called Fungus, which uses a visual flowcharting approach to dialog design.

In this recipe, we'll create a very simple, two-sentence dialogue, to illustrate the basics of Fungus. The following screenshot shows the Fungus-generated dialog for the first sentence ('Hello, how are you') and the interactive button (a triangle inside a circle) the user clicks to progress to the next piece of dialog (in the bottom-right part of the rectangle).

How to do it...

To create a two-sentence dialog using Fungus, follow these steps:

  1. Download the latest version of the Fungus unitypackage from the FungusGames website http://www.fungusgames.com/.

  2. Create a new Unity 2D project.

  3. Import the Fungus unitypackage by navigating to Assets | Import Package | Custom Package..., and then navigating to your downloaded file location.

  4. Create a new Fungus Flowchart GameObject by choosing menu: Tools | Fungus | Create | Flowchart.

  5. Display and dock the Fungus Flowchart window panel by choosing menu: Tools | Fungus | Flowchart Window.

  6. There will be a block in the Flowchart Window. Click on this block to select it (a green border appears around the block to indicate that it is selected), and then in the Inspector panel, change the name of this block to Start, as shown in the following screenshot:

  7. Each Block in a Flowchart follows a sequence of commands. So, we are now going to create a sequence of commands to display two sentences to the user when the game runs.

    Note

    The sequence of Commands in a Block

    Each Block in a Flowchart follows a sequence of Commands, so to display two sentences to the user when the game runs, we need to create a sequence of two Say commands in the Inspector panel properties for our Block.

  8. Ensure that the Start block is still selected in the Flowchart panel. Now, click on the plus +' button at the bottom section of the Inspector panel to display the menu of Commands, and select the Narrative | Say command, as shown here:

  9. Since we only have one command for this block, that command will automatically be selected (highlighted green) in the top-half part of the Inspector view. The bottom half of the Inspector view presents the properties for the currently selected Command, as shown in the following screenshot. In the bottom-half part of the Inspector view, for the Story Text property, enter the text of the question that you wish to be presented to the user: How are you today?

  10. Now, create another Say Command, and type the following for its Story Text property: Very well thank you.

  11. When you run the game, the user will first be presented with the How are you today? text (hearing a clicking noise as each letter is typed on screen). After the user clicks on the 'continue' triangle button (at the bottom-right part of the dialog window), they will then be presented with the second sentence: Very well thank you.

How it works...

You have created a new Unity project, and imported the Fungus asset package, containing the Fungus Unity menus, windows and commands, and also the example projects.

You have added a Fungus Flowchart to your scene with a single Block that you have named Start. Your block starts to execute when the game begins (since the default for the first block is to be executed upon receiving the Game Started event).

In the Start block, you added a sequence of two Say Commands. Each command presents a sentence to the user, and then waits for the continue button to be clicked before proceeding to the next Command.

As can be seen, the Fungus system handles the work of creating a nicely presented panel to the user, displaying the desired text and continue button. Fungus offers many more features, including menus, animations, control of sounds and music, and so on, details of which can be found by exploring their provided example projects, and their websites:

 

Setting custom mouse cursor images


Cursor icons are often used to indicate the nature of the interaction that can be done with the mouse. Zooming, for instance, might be illustrated by a magnifying glass. Shooting, on the other hand, is usually represented by a stylized target. In this recipe, we will learn how to implement custom mouse cursor icons to better illustrate your gameplay—or just to escape the Windows, OSX, and Linux default GUI. The following screenshot shows a custom magnifying glass mouse cursor when the use's mouse pointer hovers over a Button:

Getting ready

For this recipe, we have prepared the images that you'll need in a folder named IconsCursors in the 1362_01_13 folder.

How to do it...

To make a custom cursor appear when the mouse is over a GameObject, follow these steps:

  1. Create a new Unity 2D project.

  2. Add a Directional Light item to the scene by navigating to Create | Light | Directional light.

  3. Add a 3D Cube to the scene, scaled to (5, 5, 5). Because it was created as a 2D project the cube will appear as a grey square in the Game panel (2D projects have an orthographic camera, so we won't see perspective effects).

  4. Import the provided folder called IconsCursors.

    Tip

    Ensure that each image in this folder has been imported as Texture Type Cursor. If they are not, then select this type for each image and click on the Apply button in the Inspector view.

  5. Create a C# script class called CustomCursorPointer, containing the following code, and add an instance as a scripted component to the Cube GameObject:

    using UnityEngine;
    using System.Collections;
    
    public class CustomCursorPointer : MonoBehaviour {
      public Texture2D cursorTexture2D;
    
      private CursorMode cursorMode = CursorMode.Auto;
      private Vector2 hotSpot = Vector2.zero;
    
      public void OnMouseEnter() {
        SetCustomCursor(cursorTexture2D);
      }
    
      public void OnMouseExit() {
        SetCustomCursor(null);
      }
    
      private void SetCustomCursor(Texture2D curText){
        Cursor.SetCursor(curText, hotSpot, cursorMode);
      }
    }

    Note

    Event methods OnMouseEnter() and OnMouseExit() have been purposely declared as public. This will allow these methods to also be called from UI GameObjects when they receive the OnPointerEnterExit events.

  6. With the Cube item selected in the Hierarchy panel, drag the CursorTarget image into the public Cursor Texture 2D variable slot in the Inspector panel for the Customer Cursor Pointer (Script) component.

  7. Save the current scene, and add it to the Build.

    Tip

    You will not be able to see the custom cursors in the Unity Editor. You must build your game application, and you'll see the custom cursors when you run the build app.

  8. Build your project. Now, run your built application, and when the mouse pointer moves over the grey square of the Cube, it will change to the custom CursorTarget image that you chose.

How it works...

You have added a scripted object to a cube that will tell Unity to change the mouse pointer when an OnMouseEnter message is received—that is, when the user's mouse pointer moves over the part of the screen where the cube is being rendered. When an OnMouseExit event is received (the users mouse pointer is no longer over the cube part of the screen), the system is told to go back to the operating system default cursor. This event should be received within a few milliseconds of the user's mouse exiting from the collider.

There's more...

There are some details that you don't want to miss.

Custom cursors for mouse over UI controls

Unity 5 UI controls do not receive the OnMouseEnter and OnMouseExit events. They can respond to the PointerEnter/Exit events, but this requires adding the Event Trigger components. To change the mouse pointer when the mouse moves over a UI element, do the following:

  1. Add a UI Button to the scene.

  2. Add an instance of the C# script class called CustomCursorPointer to the button.

  3. With Button selected in the Hierarchy panel, drag the CursorZoom image into the public Cursor Texture 2D variable slot in the Inspector panel for the Customer Cursor Pointer (Script) component.

  4. In the Inspector view, add an Event Triggers component to the Button. Choose menu: Add Component | Event | Event Trigger.

  5. Add a Pointer Enter event to your Event Trigger component, click on the plus (+) button to add an event handler slot, and drag the Button GameObject into the Object slot.

  6. From the Function drop-down menu, choose CustomCursorPointer and then choose the OnMouseEnter method.

    Note

    We have added an Event Handler so that when the Button receives a Pointer Enter (mouse over) event, it will execute the OnMouseEnter() method of the CustomCursorPointer scripted object inside the Button.

  7. Add a Pointer Exit event to your Event Trigger component, and make it call the OnMouseExit()method from CustomCursorPointer when this event is received.

  8. Save the current scene.

  9. Build your project. Now, run your built application and when the mouse pointer moves over the Button, it will change to the custom CursorZoom image that you chose.

 

Input Fields component for text entry


While many times we just wish to display non-interactive text messages to the user, there are times (such as name entry for high scores) where we wish that the user was able to enter text or numbers into our game. Unity provides the Input Field UI component for this purpose. In this recipe, we'll create a simple text input UI by making use of the default Button image and text GameObjects, and we'll add a script to respond to each new value of the input field.

Note

You can, of course, create a working text input quicker than this recipe's method by choosing menu: Create | UI | Input Field, which creates a GameObject containing an Input Field component, child text, and placeholder GameObjects, as shown in the following screenshot. However, by following the steps in this recipe, you'll learn the interrelationships between the different interface elements, because you'll be creating these connections manually from the deconstructed parts of the UI Button GameObject.

How to do it...

To create a promoted text input box to the user with faint placeholder text, follow these steps:

  1. Create a new Unity 2D project.

  2. In the Inspector view, change the background of the Main Camera to solid white.

  3. Add a UI Button to the scene. Delete the Button (Script) component of the Button GameObject (since it won't be a button, it will be an interactive text input by the time we are finished with it!).

  4. Rename the Text child GameObject of the Button component to Text-placeholder. Uncheck the Rich Text option, change the text to Enter name…, change the Alignment in Left and Top, and in the Rect Transform, set Left to 4 and Top to 7.

  5. Duplicate Text-placeholder by naming the copy Text-prompt. Change the Text of this GameObject to Name:, and set its Left position to -50.

  6. Duplicate Text-placeholder again, naming this new copy Text-input. Delete all of the content of the Text property of this new GameObject.

  7. Select Text-placeholder in the Hierarchy, and we will now make the placeholder text mostly transparent. Set the A (alpha) Color value of the Text (Script) component of this GameObject to a value that is about a quarter of its maximum value (e.g. 64).

  8. Select Text-input in the Hierarchy, and add an Input Field component by choosing menu: Add Component | UI | Input Field.

  9. Drag the Text-input GameObject into the Text Component property of Input Field, and drag the Text-placeholder GameObject into the Placeholder property.

  10. Save and run your scene. You now have a working text input UI for your user. When there is no text content, the faint placeholder text will be displayed. As soon as any characters have been typed, the placeholder will be hidden and the characters typed will appear in black text. Then, if all the characters are deleted, the placeholder will appear again.

How it works...

The core of interactive text input in Unity is the responsibility of the Input Field component. This needs a reference to a UI Text GameObject. To make it easier to see where the text can be typed, we have made use of the default rounded rectangle image that Unity provides when a Button GameObject is created. Buttons have both an Image component and a Text child GameObject. So, two items that we need can be acquired very easily by creating a new Button, and simply by removing the Button (Script) component.

There are usually three Text GameObjects involved with the user text input: the static prompt text (in our recipe, for example, the Name: text); then the faint placeholder text, reminding users where and what they should type; and finally the text object (with the font and color settings and so on) that is actually displayed to the user, showing the characters as they type.

At runtime, a Text-Input Input Caret GameObject is created—displaying the blinking vertical line to inform the user where their next letter will be typed. Note that the Content Type of the Input Field (Script), in the Inspector, can be set to several specific types of text input, including e-mail addresses, integer or decimal numbers only, or the password text (where an asterisk is displayed for each entered character).

There's more...

There are some details that you don't want to miss.

Executing a C# method to respond each time the user changes the input text content

Having interactive text on the screen isn't of much use unless we can retrieve the text entered to use in our game logic, and we may need to know each time the user changes the text content and act accordingly.

To add code and events to respond each time the text content has been changed by the user, do the following:

  1. Add an instance of the C# script class called DisplayChangedTextContent to the Text-input GameObject:

    using UnityEngine;
    using System.Collections;
    using UnityEngine.UI;
    
    public class DisplayChangedTextContent : MonoBehaviour {
      private InputField inputField;
    
      void Start(){
        inputField = GetComponent<InputField>();
      }
    
      public void PrintNewValue (){
        string msg = "new content = '" + inputField.text + "'";
        print (msg);
    }
    }
  2. Add an End Edit (String) event to the list of event handlers for the Input Field (Script) component. Click on the plus (+) button to add an event handler slot, and drag the Text-input GameObject into the Object slot.

  3. From the Function drop-down menu, choose DisplayChangedTextContent and then choose the PrintNewValue method.

  4. Save and run the scene. Each time the user types in new text and then presses Tab or Enter, the End Edit event will fire, and you'll see a new content text message printed in the Console window by our script, as shown in the following screenshot:

 

Toggles and radio buttons via Toggle Groups


Users make choices, and often, these choices are either to have one of two available options (for example, sound on or off), or sometimes to choose one of several possibilities (for example, difficulty level easy/medium/hard). Unity UI Toggles allows users to turn options on and off; and when combined with Toggle Groups, they restrict choices to one of the group of items. In this recipe, we'll first explore the basic Toggle, and a script to respond to a change in values. Then in the There's More section, we'll extend the example to illustrate Toggle Groups, and styling these with round images to make them look more like traditional radio buttons.

The following screenshot shows how the button's status changes are logged in the Console panel when the scene is running:

Getting ready

For this recipe, we have prepared the images that you'll need in a folder named UI Demo Textures in the 1362_01_15 folder.

How to do it...

To display an on/off UI Toggle to the user, follow these steps:

  1. Create a new Unity 2D project.

  2. In the Inspector panel, change the Background color of the Main Camera to white.

  3. Add UI Toggle to the scene.

  4. Enter First Class as Text for the Label child GameObject of the Toggle GameObject.

  5. Add an instance of the C# script class called ToggleChangeManager to the Toggle GameObject:

    using UnityEngine;
    using System.Collections;
    using UnityEngine.UI;
    
    public class ToggleChangeManager : MonoBehaviour {
      private Toggle toggle;
    
      void Start () {
        toggle = GetComponent<Toggle>();	
      }
    
      public void PrintNewToggleValue(){
        bool status = toggle.isOn;
        print ("toggle status = " + status);
      }
    }
  6. With the Toggle GameObject selected, add an On Value Changed event to the list of event handlers for the Toggle (Script) component, click on the plus (+) button to add an event handler slot, and drag Toggle into the Object slot.

  7. From the Function drop-down menu, choose ToggleChangeManager and then choose the PrintNewToggleValue method.

  8. Save and run the scene. Each time you check or uncheck the Toggle GameObject, the On Value Changed event will fire, and you'll see a new text message printed into the Console window by our script, stating the new Boolean true/false value of the Toggle.

How it works...

When you create a Unity UI Toggle GameObject, it comes with several child GameObjects automatically—Background, Checkmark, and the text Label. Unless we need to style the look of a Toggle in a special way, all that is needed is simply to edit the text Label so that the user knows what option or feature that this Toggle is going to turn on/off.

The C# scripted class called ToggleChangeManager's method called Start() gets a reference to the Toggle component in the GameObject, where the script instance is located. When the game is running, each time the user clicks on the Toggle to change its value, an On Value Changed event is fired. We then register the PrintNewToggleValue()method, which is supposed to be executed when such an event occurs. This method retrieves, and then prints out to the Console panel the new Boolean true/false value of the Toggle.

There's more...

There are some details that you don't want to miss.

Adding more Toggles and a Toggle Group to implement mutually-exclusive radio buttons

The Unity UI Toggles are also the base components, if we wish to implement a group of mutually-exclusive options in the style of radio buttons. To create such a group of related choices, do the following:

  1. Import the UI Demo Textures folder into the project.

  2. Remove the C# script class ToggleChangeManager component from the Toggle GameObject.

  3. Rename the Toggle GameObject as Toggle-easy.

  4. Change the Label text to Easy, and tag this GameObject with a new tag called Easy.

  5. Select the Background child GameObject of Toggle-easy, and in the Image (Script) component, drag the UIToggleBG image into the Source Image property.

  6. Ensure that the Is On property of the Toggle (Script) component is checked, and then select the Checkmark child GameObject of Toggle-easy. In the Image (Script) component, drag the UIToggleButton image into the Source Image property.

    Note

    Of the three choices (easy, medium, and hard) that we'll offer to the user, we'll set the easy option to be the one that is supposed to be initially selected. Therefore, we need its Is On property to be checked, which will lead to its 'checkmark' image being displayed.

    To make these Toggles look more like radio buttons, the background of each is set to the circle image of UIToggleBG, and the checkmark (which displays the Toggles that are on) is filled with the circle image called UIToggleButton.

  7. Duplicate the Toggle-easy GameObject, naming the copy Toggle-medium. Set its Rect Transform property Pos Y to -25 (so, this copy is positioned below the easy option), and uncheck the Is On property of the Toggle (Script) component. Tag this copy with a new tag called Medium.

  8. Duplicate the Toggle-medium GameObject, naming the copy Toggle-hard. Set its Rect Transform property Pos Y to -50 (so this copy is positioned below the medium option). Tag this copy with a new tag called Hard.

  9. Add an instance of the C# script class called RadioButtonManager to the Canvas GameObject:

    using UnityEngine;
    using System.Collections;
    using UnityEngine.UI;
    
    public class RadioButtonManager : MonoBehaviour {
      private string currentDifficulty = "Easy";
    
      public void PrintNewGroupValue(Toggle sender){
        // only take notice from Toggle just swtiched to On
        if(sender.isOn){
          currentDifficulty = sender.tag;
          print ("option changed to = " + currentDifficulty);
        }
      }
    }
  10. With the Toggle-easy GameObject selected, add an On Value Changed event to the list of event handlers for the Toggle (Script) component. Click on the plus (+) button to add an event handler slot, and drag the Canvas GameObject into the Object slot.

  11. From the Function drop-down menu, choose RadioButtonManager, and then choose the PrintNewGroupValue method. In the Toggle parameter slot, which is initially None (Toggle), drag the Toggle-easy GameObject.

  12. Do the same for the Toggle-medium and Toggle-hard GameObjects—so each Toggle object calls the PrintNewGroupValue(…)method of a C# scripted component called RadioButtonManager in the Canvas GameObject, passing itself as a parameter.

  13. Save and run the scene. Each time you check one of the three radio buttons, the On Value Changed event will fire, and you'll see a new text message printed into the Console window by our script, stating the tag of whichever Toggle (radio button) was just set to true (Is On).

  14. The following screenshot shows how the value corresponding to the selected radio button is logged to the Console panel when the scene is running:

 

Conclusion


In this chapter, we have introduced recipes demonstrating a range of Unity 5 UI components, and illustrated how the same components can be used in different ways (such as an interactive slider being used to display the status of a countdown timer). One set of UI components in many games are those that communicate to the user what they are carrying (or yet to pick up). We have dedicated another chapter in this book to inventories in Chapter 2, Inventory GUIs, which provides many inventory recipes and additional UI controls, such as adding interactive scroll bars.

Here are some suggestions for further reading, tutorials, and resources to help you continue your learning of UI development in Unity:

Games need fonts in a style to match the gameplay and theme. Here are some of the sources of free personal/commercial fonts suitable for many games:

About the Authors
  • Francisco Queiroz

    http://www.nongames.com

    Browse publications by this author
  • Matthew Smith

    Matt Smith is computing academic at TUDublin (Technological University of Dublin) Ireland, where he leads the DRIVE Research Group (Digital Realities, Interaction, and Virtual Environments). Matt started computer programming on a brand new ZX80 and submitted 2 games for his computing O-level exam. After nearly 10 years as a full-time student on a succession of scholarships, he gained several degrees in computing, including a Ph.D. in computational musicology. In 1985, Matt wrote the lyrics and was in the band whose music appeared on the audio cassette carrying the computer game Confuzion. Matt is a documentation author for the open-source Unity Fungus visual scripting and dialogue system.

    Browse publications by this author
  • Matt Smith

    Matt Smith is a computing academic at what will soon become the Technological University of Dublin, Ireland. Matt started computer programming on a brand new ZX80 and submitted 2 games for his computing O-level exam. After nearly 10 years as a full-time student on a succession of scholarships, he gained several degrees in computing, including a PhD in computational musicology. In 1985 Matt wrote the lyrics, and was in the band (and sang, sorry about that by the way) whose music appeared on the B-side of the audio cassette carrying the computer game Confuzion. Matt is a documentation author for the open source Fungus Unity project. With his children he studies and teaches Taekwon-Do, and all three of them are beginning guitar lessons in 2018.

    Browse publications by this author
  • Francisco Queiroz

    Chico Queiroz is a multimedia designer from Rio de Janeiro, Brazil. Chico initiated his career back in 2000, soon after graduating in Communications/Advertising (PUC-Rio), working with advergames and webgames using Flash and Director at LocZ Multimedia. Here he contributed to the design and development of games for clients, such as Volkswagen and Parmalat, along with some independent titles. Chico has a Master's Degree in Digital Game Design (University for the Creative Arts, UK). His final project was exhibited at events and festivals, such as London Serious Games Showcase and FILE. Chico has also published articles for academic conferences and websites, such as gameology.org, gamasutra.com, and gamecareerguide.com. He curated and organized an exhibition, held at SBGames 2009, which explored connections between video games and art. SBGames is the annual symposium of the Special Commission of Games and Digital Entertainment of the Computing Brazilian Society. Chico currently works as a Digital Designer at the Computer Graphics Technology Group (TecGraf), within the Pontifical Catholic University of Rio de Janeiro (PUC-Rio), where he, among other responsibilities, uses Unity to develop interactive presentations and concept prototypes for interactive visualization software. He also works as a lecturer at PUC-Rio, teaching undergraduate Design students 3D modeling and Technology/CG for Games, in which Unity is used as the engine for the students' projects.

    Browse publications by this author
Latest Reviews (26 reviews total)
Didnt get what i ordered. No physical book delivered.
Rezepte sind anschaulich er klärt und gut nachzuvollziehen
Great Unity Cookbook - ideal for selecting and using those sections that broadened and added to my students knowledge of the product in a fun way.
Unity 5.x Cookbook
Unlock this book and the full library FREE for 7 days
Start now