Unity for Windows IV–Creating UI and saving the highscore

image

Hi and welcome back to the Unity for Windows tutorial series. In this part we will add a GUI to our game (or you can follow these steps to add it to your own game) and then display the current score and save the highscore if you play well!

Resources

Downlod the starting project here (Part I): http://sdrv.ms/1dXRQBK

Download final project and assets from here: http://sdrv.ms/1dXRBqr

 

Open the project from Tutorial 1, or another project where you want to add the GUI.

1) Creating the GUI Game Object

a) First of all, we need to create a GameObject that will hold our GUI. Click GameObject->Create Empty
image

b) Now, click the new GameObject from the Hierachy and rename it to GUI:
image

c) Create another GameObject, but this time click Create Other –> GUI Texture:
image

d) A new GUI Texture GameObject is added to the Hierarchy:

image

e) Change the name of this to ScoreBackground and drag it in the GUI Game Object:

image

f) Cope the ScoreBG.png file from this tutorials assets folder to the games Textures folder

ScoreBG

image

This texture will be used as the background for the players score,  just to make it have some sort of container instead of just floating around in space.

g) Let’s position this by altering the properties of our new GUI Texture Game Object. Click it to see the properties:

image

First of all, we need to change the position of the GUI Texture. We do this by altering the Position Transform:
image

We set this to X:0 and Y:1.

This is because we want to have the texture in the upper-left corner of the screen.

This is how the coordinate system looks:
image

As we can see, setting the coordinates to 0,1 will put it in the upper-left corner of the screen. Think of the range between 0 and 1 as percentage. 1 is 100%. What we are saying is that the texture should be 0% from the left side of the screen and 100% from the bottom of the screen (in other words top)

If we press play, we can see the texture in the upper corner.. but right now, the center of our texture is placed at 0,1:

image

This doesnt look right. We want the upper left corner of our GUI Texture to be the center. If we change the values in the Pixel Inset property of the GUI Texture, we can change where the center of the texture should be.

If we change the X to 0 and the Y to –58 (height of the texture) we set the upper left corner of the texture to:

image

This is basically the same as 0,1 when we placed the position of the texture but now we operate with pixels instead of percent.

Press play now to see the GUI Texture at the correct position! Smilefjes

image

h) Next we need a font. First, inside the Textures folder, add a new folder called Fonts. Then add the Segoe UI font from your Windows folder to the project (it can be any True Type Font) by just drag it from the Windows Folder to the Textures folder of the project.

They should now be in the Fonts folder:
image

Delete all of them except the one named SEGOEUI my marking them and pressing Delete.

Now, click the SEGOEUI font:

image

And then click GameObject->Create Other->GUI Text

image

Drag the GUI Text Game Object inside the GUI Game Object:
image

Now, if you click it to view the properties, you can see that it got the font we highlighted when we created it. Smilefjes

If you press play, you can see the text in the center of the screen saying GUI Text.

We must now place this above the GUI Texture created earlier. Change the position of the GUI Text to this:
image

We place the text a few fixels from the left side of the screen and also a few pixels from the top of the screen.

We also set the Z to 0. This means that it should be rendered above the items at Z:0 like our GUI Texture. The Z is used to control the order of the items we want to render in the GUI.

Let’s also change the size of the font to 24:

image

Press play now to see our score container in action!
image

 

2) Setting the score and saving highscore

Next, we need to set the score of the player, and then when Game Over, check it against the high score. We also need to store the high score so we don’t loose it when we quit the game.

To do this, we got something called PlayerPrefs. It’s a way Unity can store simple data like integeres (numbers) and text.

a) In the GameController class, add a new GUIText variable called scoreText:

using UnityEngine;
using System.Collections;

public class GameController : MonoBehaviour {
    public GameObject enemy;
    public GameObject laser;
   
public GUIText scoreText;

    float spawnTimer;
    float shootTimer;

    // Use this for initialization
    void Start () {
        spawnTimer = 1.0f;
    }

   
    // Update is called once per frame
    void Update () {
        spawnTimer -= Time.deltaTime;
        shootTimer -= Time.deltaTime;

        if (spawnTimer <= 0.0f)
        {
            GameObject instance = (GameObject)Instantiate(enemy,
                new Vector3(10,Random.Range(-4.0f,4.0f),-2.0f),
                transform.rotation);
            spawnTimer = 1.0f;
        }
        if (shootTimer <= 0.0f)
        {
            if (Input.GetButton(“Fire1”))
            {
                Vector3 spawnLaserPos = Camera.main.ScreenToWorldPoint(
                    new Vector3(-5.0f,
                        Input.mousePosition.y,
                        8));

                Instantiate(laser, spawnLaserPos, Quaternion.identity);
                shootTimer = 0.4f;
            }
        }
    }
}

Now save the script and go to Unity, and click the Main Camera object to view the properties. You can see the GUI Text scoreText:
image

Now, drag the GUI Text Game Object we created inside the GUI Game Object to this property:

image

b) Next, we need to connect this filed with the players score. Go back to the GameController script and add a new line in the update function:

using UnityEngine;
using System.Collections;

public class GameController : MonoBehaviour {
    public GameObject enemy;
    public GameObject laser;
    public GUIText scoreText;

    float spawnTimer;
    float shootTimer;

    // Use this for initialization
    void Start () {
        spawnTimer = 1.0f;
    }

   
    // Update is called once per frame
    void Update () {
        spawnTimer -= Time.deltaTime;
        shootTimer -= Time.deltaTime;

        scoreText.text = PlayerPrefs.GetInt(“CurrentScore”, 0).ToString();

        if (spawnTimer <= 0.0f)
        {
            GameObject instance = (GameObject)Instantiate(enemy,
                new Vector3(10,Random.Range(-4.0f,4.0f),-2.0f),
                transform.rotation);
            spawnTimer = 1.0f;
        }
        if (shootTimer <= 0.0f)
        {
            if (Input.GetButton(“Fire1”))
            {
                Vector3 spawnLaserPos = Camera.main.ScreenToWorldPoint(
                    new Vector3(-5.0f,
                        Input.mousePosition.y,
                        8));

                Instantiate(laser, spawnLaserPos, Quaternion.identity);
                shootTimer = 0.4f;
            }
        }
    }
}

What we do here is to set the texture property of our GUI Text object. It can be whatever you want. We set it to the integer found in the PlayerPrefs called CurrentScore. It does not exist yet, so it will be set to 0 as thats the default value we have chosen for it.

PlayerPrefs.GetInt(“CurrentScore”, 0).ToString();

In other words, the code does this. Find the integer CurrentScore from Player prefs. If it doesnt exist, set it to 0.

c) Now, we must give the player some score when he/she manages to shoot down a spaceship!

In the enemy script EnemyController.cs, let’s add a function that gives the player some score, and then call the script when an enemy dies:

using UnityEngine;
using System.Collections;

public class EnemyController : MonoBehaviour {
    public float speed;
    public GameObject explosion;
    // Use this for initialization
    void Start () {
    }

    void AddScore()
    {
        int _tempScore = PlayerPrefs.GetInt(“CurrentScore”);
        _tempScore += 10;
        PlayerPrefs.SetInt(“CurrentScore”, _tempScore);
    }

    void OnCollisionEnter(Collision other)
    {
        if (other.gameObject.tag.Equals(“Laser”))
        {
            Destroy(other.gameObject);
            Destroy(this.gameObject);
            Instantiate(explosion, this.transform.position, this.transform.rotation);
            AddScore();
        }
    }

    // Update is called once per frame
    void Update () {
        this.transform.position -= new Vector3(speed, 0, 0) * Time.deltaTime;

        if (this.transform.position.x <= -10.0f)
        {
            GameOver();
        }
    }

    void GameOver()
    {
        Application.LoadLevel(1);
    }
}

What we do here is to get the score stored in PlayerScore, add 10 to it, and then store it back. There are MANY ways to do this, like using a singelton or a static integer, but just to show you the PlayerPrefs class, I decided to go this way.

The problem with this score right now is that it will not be reset if you quit the game or when you start a new game after game over. In the GameController script, we must set this to 0 when we start the game. Let’s do this now. Open the GameController script and make the following changes:

using UnityEngine;
using System.Collections;

public class GameController : MonoBehaviour {
    public GameObject enemy;
    public GameObject laser;
    public GUIText scoreText;

    float spawnTimer;
    float shootTimer;

    // Use this for initialization
    void Start () {
        spawnTimer = 1.0f;
        PlayerPrefs.SetInt(“CurrentScore”, 0);
    }

   
    // Update is called once per frame
    void Update () {
        spawnTimer -= Time.deltaTime;
        shootTimer -= Time.deltaTime;

        scoreText.text = PlayerPrefs.GetInt(“CurrentScore”, 0).ToString();

        if (spawnTimer <= 0.0f)
        {
            GameObject instance = (GameObject)Instantiate(enemy,
                new Vector3(10,Random.Range(-4.0f,4.0f),-2.0f),
                transform.rotation);
            spawnTimer = 1.0f;
        }
        if (shootTimer <= 0.0f)
        {
            if (Input.GetButton(“Fire1”))
            {
                Vector3 spawnLaserPos = Camera.main.ScreenToWorldPoint(
                    new Vector3(-5.0f,
                        Input.mousePosition.y,
                        8));

                Instantiate(laser, spawnLaserPos, Quaternion.identity);
                shootTimer = 0.4f;
            }
        }
    }
}

This sets the CurrentScore to 0 when a new game is started (the Start() function will run only once when the GameController script is executed for the first time).

3) What about the highscore?

a) In the gameOver scene, we want to display the highscore. First of all, we need to check if the player got a highscore, and if yes, save it. Open the GameOverController script and make these changes:

using UnityEngine;
using System.Collections;

public class GameOverController : MonoBehaviour {
    float gameOverTimer;

    void CheckHighscore()
    {
        int _score = PlayerPrefs.GetInt(“CurrentScore”, 0);
        int _highscore = PlayerPrefs.GetInt(“HighScore”, 0);
        if (_score > _highscore)
            PlayerPrefs.SetInt(“HighScore”, _score);
    }

    // Use this for initialization
    void Start () {
        gameOverTimer = 5.0f;
        CheckHighscore();
    }
   
    // Update is called once per frame
    void Update () {
        gameOverTimer -= Time.deltaTime;
        if(gameOverTimer <= 0.0f)
            Application.LoadLevel(0);
   
    }
}

Nothing should be new here. We get the score and the highscore and check if we got a score better than the highscore. if yes, store them.

b) Now, it would be nice to see the highscore and what score the player got. Create another Game Object in the Game Over scene and name it GUI, and select the SEGOEUI font:
image

Create a new GUI Text like we did before and name this ScoreText. Do the same step to create another GUI Text named HighScoreText.

You should now have two GUI Text objects:

image

c) Set the transform of the GUI Game Object to X:0, Y:0 and Z:0
image

d) Set the transform of the ScoreText to this:

image

e) Set the tranform of the HighScoreText to this:

image

Your result should be something like this:

image

f) Let’s set these in the script:

using UnityEngine;
using System.Collections;

public class GameOverController : MonoBehaviour {
    float gameOverTimer;

    public GUIText scoreText;
    public GUIText highScoreText;

    void CheckHighscore()
    {
        int _score = PlayerPrefs.GetInt(“CurrentScore”, 0);
        int _highscore = PlayerPrefs.GetInt(“HighScore”, 0);
        if (_score > _highscore)
            PlayerPrefs.SetInt(“HighScore”, _score);
    }

    // Use this for initialization
    void Start () {
        gameOverTimer = 5.0f;
        CheckHighscore();

        scoreText.text = “Score: ” + PlayerPrefs.GetInt(“CurrentScore”, 0);
        highScoreText.text = “Highscore: ” + PlayerPrefs.GetInt(“HighScore”, 0);
    }
   
    // Update is called once per frame
    void Update () {
        gameOverTimer -= Time.deltaTime;
        if(gameOverTimer <= 0.0f)
            Application.LoadLevel(0);
   
    }
}

What happens here is that we create two new public containers for our GUI Text objects, and then we set these to the values we find in the PlayerPrefs world.

Now, in Unity, drag the two GUI Text objects to the correct containers in the property view of Main Camera:

image

Go back to the gameScene and press play. Play the game for a while (it’s currently very easy) and die. You should now see the score system working well! Smilefjes

image

image

Final words

In this tutorial we have created one component of the UI. This component is set relative to the screen. When designing UI for devices with variable resolutions it’s very important to keep in mind that you want the have a flexible UI. By creating a UI of many objects that are placed say 10% from the left side of the screen and so on, the UI adapts to different resolutions.

Many are creating a picture that is having the resolution of the screen and then just scales this based on the games resolution. This will mostly be ugly on different devices and is hard to work with.

The UI in this game will look about the same on all devices like mobiles, tablets and computers.

Download final project and assets from here: http://sdrv.ms/1dXRBqr

Advertisements
This entry was posted in Unity, Windows 8, Windows Phone. Bookmark the permalink.

One Response to Unity for Windows IV–Creating UI and saving the highscore

  1. Pingback: Unity for Windows V–Connecting To The Cloud with Windows Azure Mobile Services | digitalerr0r

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s