My journey becoming a Unity game developer: Ease of Building UI Elements in Unity.

Rhett Haynes
7 min readAug 17, 2022

--

Objective: Creating User Interface to show the player’s score onscreen, as well as the amount of lives they have left.

User Interface system used to show the Player’s progress in the game.

We need to allow the Player to see their progress onscreen in the game through a points system, and how many lives the Player has left in the game. To do this we need to use Unity’s User Interface system features such as creating a Canvas, positioning and animating elements, defining user interactions, and sizing layouts.

To setup our User Interface, we will need to use Unity’s TextMeshPro system. TextMeshPro provides high-quality text, and is now the default User Interface system installed automatically with Unity 2021 versions or higher. If you are using an older version, go to Window->Package Manager, under Unity Registry select TextMeshPro, and click Install.

Downloaded TextMeshPro through the Package Manager.

To check if TextMeshPro is installed in your editor, go inside the Projects folder, and check inside the Packages folder.

TextMeshPro installed inside of the Packages folder.

To use TMP, we need to install its Essential Resources through Window->TextMeshPro->Import TMP Essential Resources. With all the resources selected, click the Import button to import these resources into your game.

Imported TMP Essential Resources.

In the Hierarchy, use the Create drop-down and select UI->Text-TextMeshPro. Rename text object Score_text as this object will show the Player’s score. The Canvas in which all UI elements are show onscreen will be automatically added into the Hierarchy.

To align the Score text field to the right corner, click on the Anchor alignment box under Rect Transform. Select top-right to set the field’s pivot, and ALT-select to set the field itself to the top-right corner. Use the Alignment setting to position the text inside the field. Use the Font Size to change the fonts size. Also, use the Vertex Color to change the text’s color, or you can turn on the Color Gradient to used over the Vertex Color to blend in multiple colors into the text. Finally, in the Text field’s box type in “SCORE: “ to show this text onscreen.

Demonstration on the Score Text field.

We can use imported fonts as well if we don’t want to use the default fonts. Inside the newly created Fonts folder under Assets in the Project folder, drag in your downloaded fonts. These fonts will not work until they’re converted from Unity’s font format to TMP SDF format. To convert the font file, go to Window->TextMeshPro->Font Asset Creator. Drag the font file into Source Font File slot, click Generate Font Atlas to create an atlas texture and material for the font. After the conversion, click Save As and save as a new file inside the Fonts folder. Once finished, the new font file will be saved in a SDF TMP_Font Asset format. With the Score_text object selected, go to Main Settings and drag the new SDF font file into the Font Asset slot. We will see our new fonts displayed onscreen with the associated text.

Imported fonts are setup through the Font Asset Creator to be used in Unity.

Next, we need to add a scoring system for the player to score points after each enemy it destroys. Inside the PlayerBehavior script, create a new variable with a SerializeField Type int name _score to hold the points the player gains with a default of zero. Then create a Public Type Void method name AddScore() with a parameter passed in Type int name points. When points are passed in, we will use the _score variable to add points to it each time the amount of points are passed in.

AddScore() method created to add points to the player when they destroy enemies.

In the EnemyBehavior script, create a variable to serve as a handle to the Player script component name _player. Inside the Start() function, use the _player variable and look for a Game Object by Finding the Game Object With a Tag named “Player”, and Get the Component of the Player. Inside the OnTriggerEnter() under the “LaserIF condition, check IF the Player is not equal to NULL. If it isn’t, use the _player variable to get the AddScore() method and pass in 20pts for each enemy destroyed by the player’s lasers.

Player collects 20 points when Laser collides with enemies.

Now since we created a global _player variable to use in this EnemyBehavior script, we can delete the local player variable inside the “PlayerIF condition. Also, we must add underscores to the front of the player variables used before to use the correct _player variable.

With the Player object selected, play the game, destroy enemies with your lasers, and notice the score changing inside the Score variable slot under the Player script component.

Player scores 20 points with each enemy it destroys.

Inside the UI Manager script, create a new variable with a SerializeField Type TMPro.TMP_Text name _scoreText as this will hold the Score_text object inside it. Inside the Start() function, use the _scoreText.text variable to access the text field and show “SCORE: + 0 appended to the end of this statement. This will start the game with the word “SCORE:” showing onscreen as well as zero representing the player’s score starting the game.

Then, delete the Update() function since we’re not using it at this moment, and create a new method that’s Public Type Void name UpdateScore(). We’re going to pass in a parameter of TYPE INT name playerScore. Use the _scoreText.text to change to the Score field onscreen with “SCORE: “ + playerScore.ToString(). The playerScore.ToString() will convert the numbers onscreen from numbers that can calculated to string characters.

UpdateScore() method created to show the player’s score onscreen.

In the PlayerBehavior script, create a new variable name _uiManager to be a handle to the UI Manager. Inside the Start() function, use the _uiManager variable to access the UI Manager component. Also, check to see IF the _uiManager equals NULL. If so, send a Debug LogError message notifying the UI Manager is missing. Inside the AddScore() method, use the _uiManager to access the UpdateScore() method and pass in the _score variable to update the Player’s score.

Using the Player’s AddScore() method to update the score onscreen.

The score is updating onscreen after every enemy destroyed by the Player’s lasers.

Player’s score updated onscreen after every enemy destroyed by lasers.

To show the Player’s lives onscreen, we will use images to show how many lives the Player has. Right-click on the Canvas object, select UI->Image, and rename it Lives_display. Drag the Three lives image into the Source Image slot under Image. Position this image to the left-top corner using the Anchor settings. Since our image is elongated, go to the Image component and turn on Preserve Aspect which will preserve the sprite image original aspect ratio. Use the Rect Transform to make any adjustments with the image placement onscreen.

Lives display created to show how many lives the player has.

In the UI Manager script, create a new SerializeField Type Sprite[] array variable name _liveSprites to access the 4 different Lives sprite sheets that will be assigned to this array.

After saving, go to the Canvas’ UI Manager script component. Inside the Live Sprites slot we need to type in 4 to represent how many elements we need to hold our sprite sheets. Drag in each sprite sheet representing how many lives the Player have to the element slot number matching those lives.

Lives Sprites variable created to hold the 4 different lives displays.

Create another new SerializeField Type Image variable name _livesImage to access the Lives_display game object in particular the Source Image setting under the Image component. Save and go to the UI Manager script component, there drag the Lives_display game object into the Lives Image slot.

Lives Image variable created to access the Lives_display object’s image.

Back in the UI Manager script, create a new method that’s Public Type Void name UpdateLives(). Add a parameter Type INT name currentLives that will have the Player’s current lives passed in. Use the _livesImage variable to access the sprite associated with the Image component’s Source Image. Have it equal the currentLives element number passed in to the _liveSprites array variable holding each of the lives sprite sheets assigned.

In the PlayerBehavior script under the Damage() method, call the UpdateLives() method through the _uiManager variable right after the Player loses a life. Pass in the _lives variable to the UpdateLives() method as this will give the method the number of lives left to match the element number inside the Canvas’ Live Sprites array.

Update Lives() method created to show how many lives the player has left.

As the Player dies, notice the Lives display loses a ship after each death of the player until they’re all grayed out.

Lives Image display changes after each player life lost.

--

--

Rhett Haynes
Rhett Haynes

Written by Rhett Haynes

Learning to become a Unity game developer.

No responses yet