23 min read

In this article by Simon Jackson, author of the book Unity 3D UI Essentials we will see how the new Unity UI has long been sought by developers; it has been announced and re-announced over several years, and now it is finally here. The new UI system is truly awesome and (more importantly for a lot of developers on a shoestring budget) it’s free.

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

As we start to look forward to the new UI system, it is very important to understand the legacy GUI system (which still exists for backwards compatibility) and all it has to offer, so you can fully understand just how powerful and useful the new system is. It’s crucial to have this understanding, especially since most tutorials will still speak of the legacy GUI system (so you know what on earth they are talking about).

With an understanding of the legacy system, you will then peer over the diving board and walk through a 10,000-foot view of the new system, so you get a feel of what to expect from the rest of this book.

The following is the list of topics that will be covered in this article:

  • A look back into what legacy Unity GUI is
  • Tips, tricks, and an understanding of legacy GUI and what it has done for us
  • A high level overview of the new UI features

State of play

You may not expect it, but the legacy Unity GUI has evolved over time, “adding new features and improving performance. However, because it has “kept evolving based on the its original implementation, it has been hampered “with many constraints and the ever pressing need to remain backwards compatible (just look at Windows, which even today has to cater for” programs written in BASIC (http://en.wikipedia.org/wiki/BASIC)). Not to say the old system is bad, it’s just not as evolved as some of the newer features being added to the Unity 4.x and Unity 5.x series, which are based on newer and more enhanced designs, and more importantly, a new core.

The main drawback of the legacy GUI system is that it is only drawn in screen space (drawn on” the screen instead of within it) on top of any 3D elements or drawing in your scenes. This is fine if you want menus or overlays in your title but if you want to integrate it further within your 3D scene, then it is a lot more difficult.

For more information about world space and screen space, see this Unity Answers article (http://answers.unity3d.com/questions/256817/about-world-space-and-local-space.html).

So before we can understand how good the new system is, we first need to get to grips with where we are coming from. (If you are already familiar with the legacy GUI system, feel free to skip over this section.)

A point of reference

Throughout this book, we will refer to the legacy GUI simply as GUI.

When we talk about the new system, it will be referred to as UI or Unity UI, just so you don’t get mixed-up when reading.

When looking around the Web (or even in the Unity support forums), you may hear about or see references to uGUI, which was the development codename for the new Unity UI system.

GUI controls

The legacy” GUI controls provide basic and stylized controls for use in your titles.

All legacy GUI controls are drawn during the GUI rendering phase from the built-in “OnGUI method. In the sample that accompanies this title, there are examples of all the controls in the AssetsBasicGUI.cs script.

For GUI controls to function, a camera in the scene must have the GUILayer component attached to it. It is there by default on any Camera in a scene, so for most of the time you won’t notice it. However, if you have removed it, then you will have to add it back for GUI to work.

The component is just the hook for the OnGUI delegate handler, to ensure it has called each frame.

Like “the Update method in scripts, the OnGUI method can be called several times per frame if rendering is slowing things down. Keep this in mind when building your own legacy GUI scripts.

The controls that are available in the legacy GUI are:

  • Label
  • Texture
  • Button
  • Text fields (single/multiline and password variant)
  • Box
  • Toolbars
  • Sliders
  • ScrollView
  • Window

So let’s go through them in more detail:

All the following code is implemented in the sample project in the basic GUI script located in the AssetsScripts folder of the downloadable code.

To experiment yourself, create a new project, scene, and script, placing the code for each control in the script and attach the script to the camera (by dragging it from the project view on to the Main Camera GameObject in the scene hierarchy). You can then either run the project or adorn the class in the script with the [ExecuteInEditMode] attribute to see it in the game view.

The Label control

Most “GUI systems start with a Label control; this simply “provides a stylized control to display read-only text on the screen, it is initiated by including the following OnGUI method in your script:

void OnGUI() {
GUI.Label(new Rect(25, 15, 100, 30), "Label");
}

This results in the following on-screen display:

Unity 3D UI Essentials

The Label control “supports altering its font settings through the” use of the guiText GameObject property (guiText.font) or GUIStyles.

To set guiText.font in your script, you would simply apply the following in your script, either in the Awake/Start functions or before drawing the next section of text you want drawn in another font:

public Font myFont = new Font("arial");
guiText.font = myFont;

You can also set the myFont property in Inspector using an “imported font.

The Label control forms the basis for all controls to display text, and as such, “all other controls inherit from it and have the same behaviors for styling the displayed text.

The Label control also supports using a Texture for its contents, but not both text “and a texture at the same time. However, you can layer Labels and other controls on top of each other to achieve the same effect (controls are drawn implicitly in the order they are called), for example:

public Texture2D myTexture;
void Start() {
myTexture = new Texture2D(125, 15);
}
void OnGUI() {
//Draw a texture
GUI.Label(new Rect(125, 15, 100, 30), myTexture);
//Draw some text on top of the texture using a label
GUI.Label(new Rect(125, 15, 100, 30), "Text overlay");
}

You can override the order in which controls are drawn by setting GUI.depth = /*<depth number>*/; in between calls; however, I would advise against this unless you have a desperate need.

The texture” will then be drawn to fit the dimensions of the Label field, By” default it scales on the shortest dimension appropriately. This too can be altered using GUIStyle to alter the fixed width and height or even its stretch characteristics.

Texture drawing

Not “specifically a control in itself, the GUI framework” also gives you the ability to simply draw a Texture to the screen Granted there is little difference to using DrawTexture function instead of a Label with a texture or any other control. (Just another facet of the evolution of the legacy GUI). This is, in effect, the same as the previous Label control but instead of text it only draws a texture, for example:

public Texture2D myTexture;
void Start() {
myTexture = new Texture2D(125, 15);
}
void OnGUI() {
GUI.DrawTexture(new Rect(325, 15, 100, 15), myTexture);
}

Note that in all the examples providing a Texture, I have provided a basic template to initialize an empty texture. In reality, you would be assigning a proper texture to be drawn.

You can also provide scaling and alpha blending values when drawing the texture to make it better fit in the scene, including the ability to control the aspect ratio that the texture is drawn in.

A warning though, when you scale the image, it affects the rendering properties for that image under the legacy GUI system.

Scaling the image can also affect its drawn position. You may have to offset the position it is drawn at sometimes.

For” example:

public Texture2D myTexture;
void Start() {
myTexture = new Texture2D(125, 15);
}
void OnGUI() {
GUI.DrawTexture(new Rect(325, 15, 100, 15), myTexture, "   ScaleMode.ScaleToFit,true,0.5f);
}

This will do its best to draw the source texture with in the drawn area with alpha “blending (true) and an aspect ratio of 0.5. Feel free to play with these settings “to get your desired effect.

This is useful in certain scenarios in your game when you want a simple way to “draw a full screen image on the screen on top of all the 3D/2D elements, such as pause or splash screen. However, like the Label control, it does not receive any “input events (see the Button control for that).

There is also a variant of the DrawTexture function called DrawTextureWithTexCoords. This allows you to not only pick where you want the texture drawn on to the screen, but also from which part of the source texture you want to draw, for example:

public Texture2D myTexture;
void Start() {
myTexture = new Texture2D(125, 15);
}
void OnGUI() {
GUI.DrawTextureWithTexCoords (new Rect(325, 15, 100, 15), "   myTexture ,
new Rect(10, 10, 50, 5));
}

This will pick a region from the source texture (myTexture) 50 pixels wide by “5 pixels high starting from position 10, 10 on the texture. It will then draw this to “the Rect region specified.

However, the DrawTextureWithTexCoords function cannot perform scaling, it “can only perform alpha blending! It will simply draw to fit the selected texture region to the size specified in the initial Rect.

DrawTextureWithTexCoords has also been used to draw individual sprites using the legacy GUI, which has a notion of what a sprite is.

The Button control

Unity “also provides a Button control, which comes in two” variants. The basic “Button control which only supports a single click, whereas RepeatButton supports “holding down the button.

They are both instantiated the same way by using an if statement to capture “when the button is clicked, as shown in the following script:

void OnGUI() {
if (GUI.Button(new Rect(25, 40, 120, 30), "Button"))
{
   //The button has clicked, holding does nothing
}
if (GUI.RepeatButton(new Rect(170, 40, 170, 30), "   "RepeatButton"))
{
   //The button has been clicked or is held down
}
}

Each will result in a simple button on screen as follows:

 Unity 3D UI Essentials

The controls also support using a Texture for the button content as well by providing a texture value for the second parameter as follows:

public Texture2D myTexture;
void Start() {
myTexture = new Texture2D(125, 15);
}
void OnGUI() {
if (GUI.Button(new Rect(25, 40, 120, 30), myTexture))
{ }
}

Like the Label, the “font of the text can be altered using GUIStyle or” by setting the guiText property of the GameObject. It also supports using textures in the same “way as the Label. The easiest way to look at this control is that it is a Label that “can be clicked.

The Text control

Just as “there is a need to display text, there is also a need for a “user to be able to enter text, and the legacy GUI provides the following controls to do just that:

Control

Description

TextField

This” is a basic text box, it supports a single line of text, no new lines (although, if the text contains end of line characters, it will draw the extra lines down).

TextArea

This “is an extension of TextField that supports entering of multiple lines of text; new lines will be added when the user “hits the enter key.

PasswordField

This is” a variant of TextField; however, it won’t display “the value entered, it will replace each character with a replacement character.

Note, the password itself is still stored in text form and if you are storing users’ passwords, you should encrypt/decrypt the actual password when using it. Never store characters in plain text.

 Using the TextField control is simple, as it returns the final state of the value that has been entered and you have to pass that same variable as a parameter for the current text to be displayed. To use the controls, you apply them in script as follows:

string textString1 = "Some text here";
string textString2 = "Some more text here";
string textString3 = "Even more text here";
void OnGUI() {
textString = GUI.TextField(new Rect(25, 100, 100, 30), "   textString1);
textString = GUI.TextArea(new Rect(150, 100, 200, 75), "   textString2);
textString = GUI.PasswordField(new Rect(375, 100, 90, 30), "   textString3, '*');
}

A note about strings in Unity scripts

Strings are immutable. Every time you change their value they create a new string in memory by having the textString variable declared at the class level it is a lot more memory efficient.

If you declare the textString variable in the OnGUI method, “it will generate garbage (wasted memory) in each frame. “Worth keeping in mind.

When” displayed, the textbox by default looks like this:

 Unity 3D UI Essentials

As with” the Label and Button controls, the font of the text displayed can be altered using either a GUIStyle or guiText GameObject property.

Note that text will overflow within the field if it is too large for the display area, but it will not be drawn outside the TextField dimensions. The same goes for multiple lines.

The Box control

In the “midst of all the controls is a generic purpose control that “seemingly “can be used for a variety of purposes. Generally, it’s used for drawing a “background/shaded area behind all other controls.

The Box control implements most of the features mentioned in the controls above controls (Label, Texture, and Text) in a single control with the same styling and layout options. It also supports text and images as the other controls do.

You can draw it with its own content as follows:

void OnGUI() {
GUI.Box (new Rect (350, 350, 100, 130), "Settings");
}

This gives you the following result:

 Unity 3D UI Essentials

Alternatively, you” can use it to decorate the background” of other controls, “for example:

private string textString = "Some text here";
void OnGUI() {
GUI.Box (new Rect (350, 350, 100, 130), "Settings");
GUI.Label(new Rect(360, 370, 80, 30), "Label");
textString = GUI.TextField(new Rect(360, 400, 80, 30), "   textString);
if (GUI.Button (new Rect (360, 440, 80, 30), "Button")) {}
}

Note that using the Box control does not affect any controls you draw upon it. It is drawn as a completely separate control. This statement will be made clearer when you look at the Layout controls later in this article.

The example will draw the box background and the Label, Text, and Button controls on top of the box area and looks like this:

 Unity 3D UI Essentials

The box control can” be useful to highlight groups of controls or providing “a simple background (alternatively, you can use an image instead of just text and color).

As with the other controls, the Box control supports styling using GUIStyle.

The Toggle/checkbox control

If checking “on / checking off is your thing, then the legacy” GUI also has a checkbox control for you, useful for those times when” you need to visualize the on/off state “of an option.

Like the TextField control, you “pass the variable that manages Togglestate as “a parameter and it returns the new value (if it changes), so it is applied in code “as follows:

bool blnToggleState = false;
void OnGUI() {
blnToggleState = GUI.Toggle(new Rect(25, 150, 250, 30),
blnToggleState, "Toggle");
}

This results in the following on-screen result:

Unity 3D UI Essentials

As with the Label and Button controls, the font of the text displayed can be altered using either a GUIStyle or guiText GameObject property.

Toolbar panels

The basic “GUI controls also come with some very basic” automatic layout panels: “the first handles an arrangement of buttons, however these buttons are grouped “and only one can be selected at a time.

As with other controls, the style of the button can be altered using a GUIStyles definition, including fixing the width of the buttons and spacing.

There are two layout options available, these are:

  • The Toolbar control
  • The Selection grid control

The Toolbar control

The Toolbar control “arranges buttons in a horizontal “pattern (vertical is “not supported).

Note that it is possible to fake a vertical toolbar by using a selection grid with just one item per row. See the Selection grid section later in this article for more details.

As with other controls, the Toolbar returns the index of the currently selected button in the toolbar. The buttons are also the same as the base button control so it also offers options to support either text or images for the button content.

The RepeatButton control however is not supported.

To implement the toolbar, you specify an array of the content you wish to display in each button and the integer value that controls the selected button, as follows:

private int toolbarInt;
private string[] toolbarStrings ;
Void Start() {
toolbarInt = 0;
toolbarStrings = { "Toolbar1", "Toolbar2", "Toolbar3" };
}
void OnGUI() {
toolbarInt = GUI.Toolbar(new Rect(25, 200, 200, 30), "   toolbarInt, toolbarStrings);
}

The main” difference between the preceding controls is that you” have to pass the currently selected index value in to the control and it then returns the new value.

The Toolbar when drawn looks as follows:

 Unity 3D UI Essentials

As stated, you can also pass an array of textures as well and they will be displayed instead of the text content.

The SelectionGrid control

The “SelectionGrid control is a customization “of the previous standard Toolbar control, it is able to arrange the buttons in a grid layout and resize the buttons appropriately to fill the target area.

In code, SelectionGrid is used in a very similar format to the Toolbar code shown previously, for example:

private int selectionGridInt ;
private string[] selectionStrings;
Void Start() {
selectionGridInt = 0;
selectionStrings = { "Grid 1", "Grid 2", "Grid 3", "Grid 4" };
}
void OnGUI() {
selectionGridInt = GUI.SelectionGrid(
new Rect(250, 200, 200, 60), selectionGridInt, selectionStrings, 2);
}

The main difference between SelectionGrid and Toolbar in code is that with SelectionGrid you can specify the number of items in a single row and the control will automatically lay out the buttons accordingly (unless overridden using GUIStyle).

The preceding code will result in the following layout:

 Unity 3D UI Essentials

On “their own, they provide a little more flexibility” than just using buttons alone.

The Slider/Scrollbar controls

When “you need to control a range in your games. GUI or add “a handle to control moving properties between two values, like” moving an object around in your scene, this is “where the Slider and Scrollbar controls come in. They provide two similar out-of-the-box implementations that give a scrollable region and a handle to control the value behind the control.

Here, they are presented side by side:

 Unity 3D UI Essentials

The slimmer Slider and chunkier Scrollbar controls can both work in either horizontal or vertical modes and have presets for the minimum and maximum values allowed.

Slider control code

In code, the “Slider control code is represented as follows:

private float fltSliderValue = 0.5f;
void OnGUI() {
fltSliderValue = GUI.HorizontalSlider(new Rect(25, 250, 100,30), "   fltSliderValue, 0.0f, 10.0f);
fltSliderValue = GUI.VerticalSlider(new Rect(150, 250, 25, 50), "   fltSliderValue, 10.0f, 0.0f);
}

Scrollbar control code

In code, the “Scrollbar control code is represented as follows:

private float fltScrollerValue = 0.5f;
void OnGUI() {
fltScrollerValue = GUI.HorizontalScrollbar(new Rect(25, 285,"   100, 30), fltScrollerValue, 1.0f, 0.0f, 10.0f);
fltScrollerValue = GUI.VerticalScrollbar(new Rect(200, 250, 25,"   50), fltScrollerValue, 1.0f, 10.0f, 0.0f);
}

Like Toolbar and SelectionGrid, you are required to pass in the current value and it will return the updated value. However, unlike all the other controls, you actually have two style points, so you can style the bar and the handle separately, giving you a little more freedom and control over the look and feel of the sliders.

Normally, you would only use the Slider control; The main reason the Scrollbar is available is that it forms the basis for the next control, the ScrollView control.

The ScrollView control

The last” of the displayable controls is the ScrollView control, “which gives you masking abilities over GUI elements with” optional horizontal and vertical Scrollbars. Simply put, it allows you to define an area larger for controls behind a smaller window on the screen, for example:

 Unity 3D UI Essentials

Example list implementation using a ScrollView control

Here we have a list that has many items that go beyond the drawable area of the ScrollView control. We then have the two scrollbars to move the content of the scroll viewer up/down and left/right to change the view. The background content is hidden behind a viewable mask that is the width and height of the ScrollView control’s main window.

Styling the “control is a little different as there is no base style” for it; it relies on the currently set default GUISkin. You can however set separate GUIStyles for each of the sliders but only over the whole slider, not its individual parts (bar and handle). If you don’t specify styles for each slider, it will also revert to the base GUIStyle.

Implementing a ScrollView is fairly easy, for example:

  1. Define the visible area along with a virtual background layer where the controls will be drawn using a BeginScrollView function.
  2. Draw your controls in the virtual area. Any GUI drawing between the ScrollView calls is drawn within the scroll area.

    Note that 0,0 in the ScrollView is from the top-left of the ScrollView area and not the top-left-hand corner of the screen.

  3. Complete it by closing the control with the EndScrollView function. For example, the previous example view was created with the following code:
private Vector2 scrollPosition = Vector2.zero;
private bool blnToggleState = false;
void OnGUI()
{
scrollPosition = GUI.BeginScrollView(" new Rect(25, 325, 300, 200), " scrollPosition, " new Rect(0, 0, 400, 400));

for (int i = 0; i < 20; i++)
{
   //Add new line items to the background
   addScrollViewListItem(i, "I'm listItem number " + i);
}
GUI.EndScrollView();
}

//Simple function to draw each list item, a label and checkbox
void addScrollViewListItem(int i, string strItemName)
{
GUI.Label(new Rect(25, 25 + (i * 25), 150, 25), strItemName);
blnToggleState = GUI.Toggle(" new Rect(175, 25 + (i * 25), 100, 25), " blnToggleState, "");
}

In this “code, we define a simple function (addScrollViewListItem) to “draw a list item (consisting of a label and checkbox). We then begin the ScrollView control by passing the visible area (the first Rect parameter), the starting scroll position, and finally the virtual area behind the control (the second Rect parameter). Then we “use that to draw 20 list items inside the virtual area of the ScrollView control using our helper function before finishing off and closing the control with the EndScrollView command.

If you want to, you can also nest ScrollView controls within each other.

The ScrollView control also has some actions to control its use like the ScrollTo command. This command will move the visible area to the coordinates of the virtual layer, bringing it into focus. (The coordinates for this are based on the top-left position of the virtual layer; 0,0 being top-left.)

To use the ScrollTo function on ScrollView, you must use it within the Begin and End ScrollView commands. For example, we can add a button in ScrollView to jump to the top-left of the virtual area, for example:

public Vector2 scrollPosition = Vector2.zero;
void OnGUI()
{
scrollPosition = GUI.BeginScrollView(" new Rect(10, 10, 100, 50)," scrollPosition, " new Rect(0, 0, 220, 10));

if (GUI.Button(new Rect(120, 0, 100, 20), "Go to Top Left"))
   GUI.ScrollTo(new Rect(0, 0, 100, 20));
GUI.EndScrollView();
}

You can also additionally turn on/off the sliders on either side of the control by specifying “the BeginScrollView statement “using the alwayShowHorizontal and alwayShowVertical properties; these are highlighted here in an updated “GUI.BeginScrollView call:

Vector2 scrollPosition = Vector2.zero;
bool ShowVertical = false; // turn off vertical scrollbar
bool ShowHorizontal = false; // turn off horizontal scrollbar
void OnGUI() {
scrollPosition = GUI.BeginScrollView(
new Rect(25, 325, 300, 200),
scrollPosition,
new Rect(0, 0, 400, 400),
ShowHorizontal,
ShowVertical);
GUI.EndScrollView ();
}
GUI.EndScrollView ();
}

Rich Text Formatting

Now” having just plain text everywhere would not look” that great and would likely force developers to create images for all the text on their screens (granted a fair few still do so for effect). However, Unity does provide a way to enable richer text display using a style akin to HTML wherever you specify text on a control (only for label and display purposes; getting it to” work with input fields is not recommended).

In this HTML style of writing text, we have the following tags we can use to liven up the text displayed.

Unity 3D UI Essentials

This gives” text a Bold format, for example:

The <b>quick</b> brown <b>Fox</b> jumped over the <b>lazy Frog</b>

This would result in:

The quick brown Fox jumped over the lazy Frog

Unity 3D UI Essentials

Using this tag “will give text an Italic format, for example:

The <b><i>quick</i></b> brown <b>Fox</b><i>jumped</i> over the <b>lazy Frog</b>

This would result in:

The quick brown Fox jumped over the lazy Frog

Unity 3D UI Essentials

As you can “probably guess, this tag will alter the Size of the text it surrounds.

For reference, the default size for the font is set by the font itself.

For example:

The <b><i>quick</i></b> <size=50>brown <b>Fox</b></size> <i>jumped</i> over the <b>lazy Frog</b>

This would result in:

Unity 3D UI Essentials

Unity 3D UI Essentials

Lastly, you can specify different colors for text surrounded by the Color tag. “The color itself is” denoted using its 8-digit RGBA hex value, for example:

The <b><i>quick</i></b> <size=50><color=#a52a2aff>brown</color> <b>Fox</b></size> <i>jumped</i> over the <b>lazy Frog</b>

Note that the “color is defined using normal RGBA color space notation (http://en.wikipedia.org/wiki/RGBA_color_space) in hexadecimal form with two characters per color, for example, RRGGBBAA. Although the color property does also support the shorter RGB color space, which is the same notation “but without the A (Alpha) component, for example,. RRGGBB

The preceding code would result in:

Unity 3D UI Essentials

(If you are reading this in print, the previous word brown is in the color brown.)

You can also use a color name to reference it but the pallet is quite limited; for more “details, see the Rich Text manual reference page at http://docs.unity3d.com/Manual/StyledText.html.

For text meshes, there are two additional tags:

  • <material></material>
  • <quad></quad>

These only apply when associated to an existing mesh. The material is one of the materials assigned to the mesh, which is accessed using the mesh index number “(the array of materials applied to the mesh). When applied to a quad, you can also specify a size, position (x, y), width, and height to the text.

The text mesh isn’t well documented and is only here for reference; as we delve deeper into the new UI system, we will find much better ways of achieving this.

Summary

So now we have a deep appreciation of the past and a glimpse into the future. One thing you might realize is that there is no one stop shop when it comes to Unity; each feature has its pros and cons and each has its uses. It all comes down to what you want to achieve and the way you want to achieve it; never dismiss anything just because it’s old.

In this article, we covered GUI controls.

It promises to be a fun ride, and once we are through that, we can move on to actually building some UI and then placing it in your game scenes in weird and wonderful ways.

Now stop reading this and turn the page already!!

Resources for Article:


Further resources on this subject:


LEAVE A REPLY

Please enter your comment!
Please enter your name here