• $19 Game Dev' Courses - Use code "FEBUDEMY"

    Video courses

Learn to Code by Making Games – The Complete Unity Developer

Build 7 2D & 3D games

Become a Game Developer/Designer: Complete Master Series

Massive 70 hour course!

Make VR Games in Unity with C# for multiple headsets

Google Cardboard, Oculus Rift and more.

If we are going to make a real game we will need to create a simple HUD to show things like score, highest score and perhaps some other game stats as well. In addition, our game will need a UI, buttons checkboxes etc, for things like starting. pausing and perhaps player inventories. This project will look at the simplest possible case of a HUD and a UI. We will learn how to add and use buttons at the same time we will see how to display and persist (save/keep) the players highest score, even after the player has quit the game.

unity-game-development-books-728-90

Please visit the Unity category of the Game Code School bookstore

About this project

Skill level 1
Time to complete 30 minutes

New concepts

  1. Unity UI Canvas
  2. Buttons and Text objects
  3. Responding to button click events
  4. Updating Text objects
  5. Persisting data in Unity

Adding a Canvas and a EventSystem

Start new project called UI & Data Persistence. As with all the projects so far, be sure to select the 2D option.

Right click in the Hierarchy window and select  UI | Canvas. Before a project can have any UI objects it must first have a Canvas object. In future, you can save time by adding any UI object and if you don’t have a Canvas object then Unity adds one automatically. I thought that explicitly adding it would make it clear what we are doing. Any UI objects we add, need to be a child of this Canvas. We will see this in a minute.

Notice that two objects have been added to the project, a Canvas and an EventSystem. You can’t have one without the other. The EventSystem object is what alerts our UI objects when something happens to them. The number of events we can respond to are extremely wide and varied. In this tutorial, we will only be interested in the click of a button.

Configuring the Canvas

Make sure that Canvas is selected in the Hierarchy window. Find the Render Mode option in the Inspector window and change it to Screen-space camera. Next, drag Main camera from the Hierarchy window over to the to Render Camera field. What we have just done is to set the view of the game camera, Main Camera, as the extent of our UI canvas. We can now add UI anywhere on the visible area of the player’s screen.

Adding a Button and Text objects

Right click the Canvas object in the Hierarchy window and select UI | Button. A new button has been added as a child of the Canvas object. Also notice that it automatically has a Text child object. Select the Text object by left-clicking it once and change the Text property in the Inspector window to Add one.

adding-text-to-UI-button

Now we can add a Text object. Right click the Canvas object and select UI | Text. Right-click the new  Text object and choose Rename, change its name to score.

rename-a-text-object

Change its Text property to Score, its Font Size to 25 and its Color to white(or similar easily seen color) by editing in the appropriate place in the Inspector window. This next image shows how and where to do these things.

change-text-color-to-white

Next, we need another new Text object. Create one as we just did and change its name to hiscore, its Text property to Hi Score, its Font Size to 25 and its Color to white(or similar).

Arrange your screen to look roughly like mine. You can select “move mode” by pressing W and then you can move each object individually, using the horizontal and vertical arrows. If you have trouble selecting the objects individually in the Scene window then select them one at a time from the Hierarchy window.
arranging-buttons-and-text-on-screen

 

Now we are ready to make our UI actually do something.

Writing the C# code

As we have done in previous projects we want to add an empty GameController object with a GameController C# script component. To achieve this, right-click in the Hierarchy window and select Create Empty…. Rename the new game object to GameController. Now click the Add Component button in the Inspector window, choose Script | New Script and name it GameController, then click Create and Add. Open the script to edit it and change the code to look exactly like this next code.

using UnityEngine;
using UnityEngine.UI;
using System.Collections;

public class GameController : MonoBehaviour {

    public Text scoreText;
    public Text hiscoreText;

	// the variables
    int score = 0;
    int hiscore;

    // Use this for initialization
    void Start () {
        hiscore = PlayerPrefs.GetInt ("hiscore", 0);

        scoreText.text = "Score:" + score;
        hiscoreText.text = "HiScore:" + hiscore;
    }

    // Update is called once per frame
    void Update () {

    }

    public void incrementScore(){

        // Add to the score
        score++;

        // Update the score text
        scoreText.text = "Score:" + score;

        // Is there a new hiscore?
        if (score > hiscore) {        

            // Set the new hiscore
            hiscore = score;

            // Save the new hiscore
            PlayerPrefs.SetInt ("hiscore", hiscore);

            // Update the hiscore text
            hiscoreText.text = "Hiscore:" + hiscore;
        }
    }
}

Explaining the code

Let’s do this in chunks. Near the top of the code block, we have this code.

// Two text objects
public Text scoreText;
public Text hiscoreText;

// the variables
int score = 0;
int hiscore;

The first thing to notice is that we have two objects of the type Text, scoreText and hiscoreText. It is important to know that to use objects of the type Text we needed to make them available. We did so with the second line of code we typed, using UnityEngine.UI. Next, we declare two regular int variables, score and hiscore. Here is what will happen in this project. The score and hiscore variables, as their names make plain, will be used to keep track of the score and highest score of the player. The scoreText and hiscoreText objects will be associated with the UI Text objects we have added and will be used to display the values stored in score and hiscore. Simple-ish.

Next, we coded the Start method, here it is again. Remember from previous projects that this method executes when the object first comes into use in the game. So, in this case it will execute as soon as the game starts.

// Use this for initialization
void Start () {
	hiscore = PlayerPrefs.GetInt ("hiscore", 0);

	scoreText.text = "Score:" + score;
	hiscoreText.text = "HiScore:" + hiscore;
}

Here is how this method works. The first line uses the PlayerPrefs class’ GetInt method to initialize the hiscore variable with a value, labelled as "hiscore" stored in a file associated with this game. The file is provided automatically, we don’t need to do anything to get it. If no value with the label "hiscore" exists, then the value zero is used. The first time we run the game the label "hiscore" and the associated value will not exist. Therefore the value of hiscore is zero.

Next, the code sets the text property of scoreText by concatenating the string "Score:" with whatever value is currently held in score. This, of course, is zero because that is what we initialized it to. Next, hiscoreText gets the same treatment. If, however, PlayerPrefs.GetInt had successfully initialized hiscore with a value, at this point, it would be stored as the text value in hiscoreText.

The main part of the code we just wrote is the incrementScore method. Also, notice that nowhere in our code do we actually call this method. We will fix this soon. For now, let’s look at what the code does when it is eventually called.

// Add to the score
score++;

// Update the score text
scoreText.text = "Score:" + score;

The first part, re-shown above, increments (adds one) to score then updates scoreText.text, using the new value of score, in exactly the same way that we initialized it in the Start method.

The last of the code in the incrementScore method is wrapped in a  if statement that only executes when score is greater than hiscore. In other words, the code below will execute each time a new high score is achieved by the player.

// Is there a new hiscore?
if (score > hiscore) {        

	// Set the new hiscore
	hiscore = score;

	// Save the new hiscore
	PlayerPrefs.SetInt ("hiscore", hiscore);

	// Update the hiscore text
	hiscoreText.text = "Hiscore:" + hiscore;
}

Inside the if block hiscore is set to score, the new player high score. The next line of code uses PlayerPrefs.SetInt to write the value contained in hiscore into the file provided by Unity and labeling it as "hiscore". Note that if the "hiscore" label does not exist, Unity creates it. This means that not only has the players new achievement just been saved, but also, the next time the game is run it will be loaded and displayed because of the code we wrote in the Start method. The final line of code uses the exact same code as we saw in the Start method to set the text property of the hiscoreText object.

Now our code is preparing the Text objects and score-related variables, incrementing score, checking for new player high scores and updating the appropriate Text objects. We just need to associate the Text objects in our UI with the Text objects in our script and work out how to call the incrementScore method when the player clicks the button in the UI.

Updating the UI Text and calling the incrementScore method

Back in Unity, select the GameController object in the Hierarchy window. Notice the two new fields on the Game Controller (Script) component. These are our two public Text objects.

two-new-public-fields-on-the-script-component

  1. Drag the score object from the Hierarchy window and drop it on the Score Text field of the script component in the Inspector window.
  2. Drag the hiscore object from the Hierarchy window and drop it on the Hiscore Text field.

It should look like this when you are done.

public-fields-associated-with-game-objects

Now, to make the whole thing work, we need to make the button call the incrementScore method in the GameController object. I love how easy Unity makes this.

Select the button object in the Hierarchy window by single left-clicking it. Next, click the + button in Inspector window as shown next.

adding-method-to-button-onclick-event

Now Drag the GameController object from the Hierarchy window to the (None) Object field we just added to the OnClick() event, highlighted for clarity next.

drag-object-to-onclick-event-of-button

Select the GameController | incrementScore() method from the no function drop down.

add-method-from-object-to-onclick-event

Here is what that part of the screen should look like now.

onclick-event-triggers-method

Run the game and click the Add One button. Notice that the score increases and as the hiscore was zero it increases along with the score. Don’t click too many times. Quit the game by clicking the same button you used to start the game. Now start the game again and notice that the hiscore remains.

highscore-remembered

Now start clicking again. Notice that the hiscore will begin to increase once score exceeds it. Quit and restart as many times as you like, even quit and restart Unity itself, to demonstrate that the hiscore is being saved to a file, as intended.

I know I keep saying it but we are getting really close to building a real game.