Introduction to Unity Scripting – Part 2

In the second and last part of this tutorial, you will finish the game Sheep Rescue, in which you have to save the panicking sheep from their demise! By Eric Van de Kerckhove.

Leave a rating/review
Download materials
Save for later
Share
You are currently viewing page 4 of 6 of this article. Click here to view the first page.

Manipulating User Interfaces

Of course, it's a bit silly to keep track of the score and mistakes if there's no way to view them. In order to fix that, drag Game UI from RW/Prefabs into the root of the Hierarchy. This is a pre-made Canvas with some text, a few images and a very simple game over window that's disabled.

Note: If you want to learn more about creating user interfaces in Unity, check out our Unity UI series of tutorials!

When you fully fold out Game UI, you'll see that all of the elements have unique names to show what they're used for.

To interact with the UI, you'll need another manager that will reference all of the elements and change their values based on the state of the game.

Create a new C# script in RW/Scripts/Managers, name it UIManager and open it in a code editor.

Most of the classes used for manipulating UI elements live in the UnityEngine.UI namespace. So, add this using statement below the others:

using UnityEngine.UI;

With this added, you can start adding references to UI components. Add the following variable declarations above Start:

public static UIManager Instance; // 1

public Text sheepSavedText; // 2
public Text sheepDroppedText; // 3
public GameObject gameOverWindow; // 4

Here's what these are:

  1. A reference to this UI Manager.
  2. Cached reference to the Text component of DroppedSheepText.
  3. This references the Text component of SavedSheepText.
  4. Reference to the Game Over Window.

Next, change Start to Awake and add this line to it:

Instance = this;

This stores this script inside the Instance variable to allow easy access to other scripts.

Now, delete Update and add these methods in its place:

public void UpdateSheepSaved() // 1
{
    sheepSavedText.text = GameStateManager.Instance.sheepSaved.ToString();
}

public void UpdateSheepDropped() // 2
{
    sheepDroppedText.text = GameStateManager.Instance.sheepDropped.ToString();
}

These methods update the text at the top of the screen:

  1. Get the amount of sheep saved from the Game State Manager, convert it to a string and use it to set the text of sheepSavedText.
  2. Same as the other method, but use the amount of sheep dropped instead.

Finally, add this method:

public void ShowGameOverWindow()
{
    gameOverWindow.SetActive(true);
}

This activates the Game Over Window, so it becomes visible.

That's it for this script, but you still need a way of calling its methods as the UI Manager isn't aware when a sheep was saved or dropped.

Save this script and open the GameStateManager script.

Add the following line to SavedSheep:

UIManager.Instance.UpdateSheepSaved();

This updates the text that shows the amount of sheep saved.

Next, add this line to DroppedSheep, right below sheepDropped++;:

UIManager.Instance.UpdateSheepDropped();

This calls the UI Manager to update the dropped sheep text.

Finally, add this line to GameOver:

UIManager.Instance.ShowGameOverWindow();

The game over window gets shown once the game is over with this method call. That should do it! Save this script and return to the editor.

Add a new empty GameObject as a child of Managers and name it UI Manager. Add a UI Manager component and drag the children of Game Canvas to their corresponding slots.

Now, play the game for a bit and notice the UI updates as sheep get saved and fall down. As you can see, manipulating UI elements using scripting is pretty easy!

If you let three sheep drop down, a simple game over window pops up. If you press the Escape key, the Title scene loads, but you won't be able to click any of the buttons just yet. Time to fix that!

Title Screen Buttons

Save the currently opened scene and open the Title scene from RW/Scenes. Take a look around the scene, it's the same environment as the game itself, but with some props added together and a different camera view.

Now, direct your attention to the Hierarchy and expand Main Camera, which is hiding the 3D menu elements Title, Start Button and Quit Button.

To get these buttons working, you'll be using a combination of the physics system and the event system. The physics are essential for detecting if the mouse cursor is hovering over a model, while the event system is needed to detect mouse clicks. Don't worry, it'll be crystal clear what this entails soon enough!

Start by selecting Start Button and Quit Button in the Hierarchy. Add a Box Collider to both of them and set their Size to (X:2.5, Y:1, Z:0.4). That covers the physics part.

Now, add an Event System to the Hierarchy by selecting GameObject ► UI ► Event System from the top menu. This will add a GameObject named EventSystem to the scene with an Event System and a Standalone Input Module component attached.

The event system is used to handle all sorts of mouse, keyboard, gamepad and touch input and passes the data on to the game. It's an essential part of handling player input when it comes to user interfaces. There's one more component that's needed before interacting with these buttons will work.

Select Main Camera and add a Physics Raycaster component to it. This component, as its name implies, casts rays into the scene and passes events to the event system when a 3D collider is detected (like when hovering over a button).

That should do it, the scene is now ready to be interacted with! To make use of it, you'll need to create another script. Create a new folder in RW/Scripts and name it Title.

Now create a new C# script in there named StartButtton and open it in a code editor.

For starters, add these using statements below the others:

using UnityEngine.EventSystems;
using UnityEngine.SceneManagement;

These are used so you can easily access the classes from both the event system and the scene manager.

Now, replace this line:

public class StartButton : MonoBehaviour

With this:

public class StartButton : MonoBehaviour, IPointerClickHandler

Inheriting from the IPointerClickHandler interface allows this class to receive OnPointerClick callbacks from the event system. In fact, it's required to use the method when inheriting from that interface, so you'll probably see some red squiggly lines showing up. Remove Start and Update. Add the following method to fix that:

public void OnPointerClick(PointerEventData eventData) // 1
{
    SceneManager.LoadScene("Game"); // 2
}
  1. This method needs to have a specific signature in order to work with the event system, you need a single PointerEventData parameter that holds all information you could wish for about the click event.
  2. Use the scene manager to load the Game scene.

Now, save the script and return to the editor. Select Start Button, add a Start Button component to it and take a look at the bottom of the Inspector. It now shows an extra section named Intercepted Events, which lists all of the events that will be passed from the event system onto the selected GameObject.

In this case, when you click this GameObject, OnPointerClick will be called on StartButton, just as expected!

Next, play the scene and click on the Start button, the Game scene will be loaded.

Looking good so far! To get the quit button working, duplicate the StartButton script, name the copy QuitButton and open it in a code editor.

Replace this line:

public class StartButton : MonoBehaviour, IPointerClickHandler

With this one:

public class QuitButton : MonoBehaviour, IPointerClickHandler

This is to rename the class to match the file name. The script won't compile if the names don't match.

Now, remove this line inside of OnPointerClick:

SceneManager.LoadScene("Game");

Finally, add this in its place:

Application.Quit();

As you might've guessed, this quits the game. Save the script and return to the editor.

Select Quit Button, add a Quit Button component to it and run the scene. Try clicking the Quit button and you'll notice nothing happens. What gives?

Application.Quit does actually get called, but it will only work in an actual build. You can give it a try by building the game to an executable by pressing CTRL (or CMD) + B and selecting a folder to deploy to. After the game has launched, try clicking the Quit button again, it will close the game as expected now.

There's one final adjustment to the buttons that will make it more clear to the player that they can be clicked, and that's by changing their color when the mouse cursor hovers over them. Create a new C# script in RW/Scripts/Title, name it ChangeColorOnMouseOver and open it in a code editor.

Add this familiar using statement below the others to allow use of the event system:

using UnityEngine.EventSystems;

Now, replace this line:

public class ChangeColorOnMouseOver : MonoBehaviour

With this one:

public class ChangeColorOnMouseOver : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler

Just like IPointerClick, these pointer event interfaces are used to react to events triggered by the event system. In this case, they supply methods for when the pointer enters and exits the GameObject. You will get some errors again about not implementing the interface members, but ignore those for now, they'll disappear once you add the methods.

Now, add these variable declarations right above Start:

public MeshRenderer model; // 1
public Color normalColor; // 2
public Color hoverColor; // 3

Here's what these are used for:

  1. A reference to the mesh renderer that needs its color changed.
  2. The default color of the model.
  3. The color that should be applied on the model when the pointer is hovering over it.

Now, add this to Start:

model.material.color = normalColor;

This changes the model's color to the normal one.

Now, remove Update and add these methods in its place:

public void OnPointerEnter(PointerEventData eventData) // 1
{
    model.material.color = hoverColor;
}

public void OnPointerExit(PointerEventData eventData) // 2
{
    model.material.color = normalColor;
}

These methods will be called when a pointer enters and exits the attached GameObject:

  1. This is another method that needs to have a single PointerEventData variable as its parameter. It gets called when the pointer enters the GameObject and changes the color of the model's material.
  2. Called when the pointer exits the GameObject. This resets the color of the material to its normal value.

That's it! Save this script and return to the editor. Select both buttons and add a Change Color On Mouse Over component to each.

Set the alpha value of Normal Color to 100 and change its hexadecimal value to CCCCCC (a light grey) on both buttons.

Now, do the same for Hover Color, but set its hexadecimal color value to pure white, FFFFFF. Next, select just the Start Button and drag its child onto the Model slot.

Now, do the same for Quit Button and play the scene. Hover over the buttons with your cursor and you'll notice they change color.

The full game is done now! However, there's one more technique to share with you: How to pass data between scenes.