Infinite Roller Tutorial Eight – Scoring and Saving High Scores

Welcome to Edge of Code’s series of Infinite Roller tutorials. If you’d prefer a video tutorial, you can find one here.

In the previous tutorial, we randomised the height of the terrain. Today, we’ll add scoring and keep track of the player’s high score.

At the moment, we’ll make scoring simple – the player’s score will be the number of seconds they’ve kept the character alive for. If we add things for the character to pick up later, we could add extra points for collecting those.

Open your Infinite Roller project and the scene, then go to the Scripts folder in the Project window and create a new C# script (Right click, go to Create → C# Script) called ScoreSetter.

Delete the existing code inside the class and create two new class variables,

//keep track of the score
private float floatScore;

//holds the time from when this script is loaded
private float startTime; 

floatScore is a float version of the current score, and we’ll convert it to an int before displaying it. startTime is the time since the script was loaded, or since we started a new game. To initialise startTime, create an Awake method

void Awake()
{
	//set the startTime
	startTime = Time.time;
}

Time.time gives the current time in seconds since the beginning of the game. Create an Update method – we want to update the score every frame.

void Update()
{
	//update the score by how much time has passed
	floatScore = Time.time - startTime;
	int intScore = GetIntScore();
}

The floatScore variable is updated to be the difference between the current time and the startTime that we set at the beginning of the game. Note that Time.time stops when the Time.timeScale variable is set to zero (when the game is paused). Since we’ll want to display an int, not a float on the screen, create the new method

/** Round the score to an int */
public int GetIntScore()
{
	return Mathf.RoundToInt(floatScore);
}

The method is public because we’ll need to use it when setting a new high score later. The method uses Mathf’s method RoundToInt to round the float version of the score to an integer.

Unity tutorial score setter

Save the script and go back to Unity, then select the Score gameobject in the hierarchy. It’s a child of the HUD gameobject. Add the ScoreSetter script as a component to this gameobject by dragging it onto the inspector.

Unity tutorial score setter add component

We’re going to need a reference to the gameobject’s Text component to display the score, so go back to the ScoreSetter script and add a new class variable,

//score text
private Text text; 

Initialise it in Awake() using the GetComponent method:

//set the text
text = GetComponent<Text>();

And in Update(), we’ll set it’s text variable with the score, but first, create a new const class variable

private const string SCORE_TEXT = "Score: ";

This will always be the start of the text we want to display. Next, add

//set the text
text.text = SCORE_TEXT + intScore.ToString();

to the end of the Update method, after intScore has been set. To access to the Text class, add

using UnityEngine.UI;

to the top of the ScoreSetter class.

Save the script and play the game to check the score is updated correctly as you move along. If you play the game for a while, you would eventually notice that the score becomes truncated. To stop this from happening, select Score in the hierarchy and change the Width in the RectTransform to 350. This should be big enough, but you can increase it further if you want.

Next, we want the score to display on the menu once the game is over instead of it saying “Your score is SCORE.” like it does at the moment. We added this text in GameController, so open it and find the SetGameInfoText method. We’re going to need a reference in this class to the ScoreSetter – create a new class variable

public ScoreSetter score;

Save the script, go back to Unity and select GameController in the hierarchy. Drag the Score gameobject onto the new slot.

Unity tutorial score setter

Rewrite the SetGameInfoTest method:

private void SetGameInfoText()
{
	int intScore = score.GetIntScore();
	info.text = initialInfoText + "\n\nYour score is " + intScore + ". This is or maybe is not a new high score.";
}

Save and play the game to check your score displays correctly on the menu. We’ll add code to reset the score when we start a new game later in the tutorial. First, create a new script called HighScoreSetter and open the file. Delete the existing code and add

using UnityEngine.UI;

to the top of the file as we again want to access the Text class. Create a new private Text variable,

private Text text;

This script will be added as a component of the HighScore gameobject which has a Text component, so we can use GetComponent to initialise text:

void Awake()
{
	text = GetComponent<Text>();
}

Next, if a high score has been set, we want to retrieve that information and display it. Create a class variable

private const string HIGHSCORE_TEXT = "High Score: ";

This text will be at the start of the high score text. Next, create a new string class variable

private string highScoreKey;

And in Awake(), intialise it,

highScoreKey = Application.loadedLevelName;

Application.loadedLevelName gets the name of the level currently loaded, and we use the highScoreKey variable as the key to store and retrieve the player’s high score.

Create a new method

/**displays the high score */
private void SetHighScoreText()
{
	int highScore = PlayerPrefs.GetInt(highScoreKey);
	text.text = HIGHSCORE_TEXT + highScore;
}

PlayerPrefs.GetInt returns the integer stored with the key highScoreKey. We then set the text to be the initial high score text plus the integer high score. Call the SetHighScoreText method from Awake (after the highScoreKey is initialised):

void Awake()
{
	text = GetComponent<Text>();

	highScoreKey = Application.loadedLevelName;
			
	//set the high score text
	SetHighScoreText();
}

We also need to set a new high score when a game has been played. First, create a method to check whether the score is a new high score or not:

/* Check if score is a new high score*/
public bool IsNewHighScore(int score)
{
	bool isNewHighScore = false;
	
	//get the old one
	int highScore = PlayerPrefs.GetInt(highScoreKey);
	
	if (score > highScore)
	{
		isNewHighScore = true;
	}
	
	return isNewHighScore;
}

It’s public because we will call it from GameController. Inside the method, we create a local bool variable called isNewHighScore and set it to true if the new score is higher than the current high score.

To actually set the high score, create another method:

/** Set a new highscore */
public void SetNewHighScore(int score)
{
}

Again, this method is public so that we can call it from another script, and the score is passed in so that we can set it as the new highscore.

//set the new one
PlayerPrefs.SetInt (highScoreKey, newHighScore);
			
//display it
text.text = HIGHSCORE_TEXT + newHighScore;

PlayerPrefs.SetInt takes the highScoreKey and the new score as parameters, and saves it on your device, ready to be retrieved using PlayerPrefs.GetInt(highScoreKey); either later on in the same game or when you play the game again at a future date.

Unity tutorial high score

Save the script and go back to Unity, then select the HighScore gameobject in the hierarchy and add the HighScoreSetter script as a component.

Open the GameController script and create a new public variable

//ref to the highscore
public HighScoreSetter highScoreSetter;

Save the script and go back to Unity, select the GameController gameobject in the hierarchy, then drag the HighScore gameobject onto the HighScoreSetter slot. Go back to the GameController script and remove the info.text line in SetGameInfoText(). After the line initialising intScore, check if that’s a new high score using the method we just created in HighScoreSetter:

//and check if it's a new high score
bool isNewHighScore = highScoreSetter.IsNewHighScore(intScore);

We want the info to display different text depending on whether the player got a new high score or not, so add a new string variable to store the text,

//start of the info text to set
string infoText = initialInfoText + "\n\nYour score is " + intScore + ". ";

Then if the player got a new high score, add on a congratulatory message. If not, add on a different message:

//if it's a new high score, add a nice message.
if (isNewHighScore)
{
	infoText += "Well done! This is a new high score.";
}
else
{
	infoText += "This isn't a new high score. Rubbish. Maybe you should try again.";
}

Finally, set the info.text

info.text = infoText;

Create another new method

/* Set a new highscore */
private void SetHighScore()
{
	//get the score
	int intScore = score.GetIntScore();
	
	//set a new high score if it is one
	if (highScoreSetter.IsNewHighScore(intScore))
	{
		highScoreSetter.SetNewHighScore(intScore);
	}
}

To save and display the score as a high score if the player got a new one. Call this method in Update(), after SetGameInfoText();

Unity tutorial game controller

Save the script then go back to ScoreSetter. Make a new method to reset the score after each game.

/* Call between games to reset the player's score to zero*/
public void ResetScore()
{
	//reset score variable. 
	floatScore = 0;
	
	//reset the startTime. This is paused while the game is paused (when Time.timeScale = 0)
	startTime = Time.time;
}

First the floatScore variable is reset to zero. We don’t really need to do this as floatScore is reset on each frame in Update, but I’ve added it in anyway. Then startTime is reset to Time.time. We can do this as soon as the game is over rather than when the player presses the Play button because while the game is paused, this is paused too. Call this method in the RestartGame method in GameController:

//reset the score
score.ResetScore();

Unity tutorial reset score

Make sure all of the scripts are saved and go back to Unity to check everything works correctly. Your high score should persist across games, including once you’ve quit the game and restarted. Your score should start from zero on each game and increase by one each second. A different message should appear on the screen once the character dies telling you your score and whether you got a new high score or not.

Unity tutorial score and high score

I think the writing is too dark on the menu, so I’m going to change the title, info and button text to a white colour. Under the MainMenu gameobject, select Title and change the Color option to white. Do the same for Info, Play’s child Text gameobject and Quit’s child Text gameobject. Save the scene and the project.

In this tutorial, we’ve added scoring and recorded the player’s high score. Next time, we’ll look at creating your own sound effects using Audacity.

Remember you can download the files for this tutorial on the Downloads page. See you next time!

PreviousTutorialButtonNextTutorialButton

Leave a Reply

Your email address will not be published. Required fields are marked *