These can be found with a right click.
Several interface options are available
After picking ‘Text” we have a Canvas, smaller Text area, and an Event System.
Canvas and Text area
Before anchoring the UI so far, here is Color: white, Font: 20, and Position: (-26, -26, 0).
Scene and Game view before anchoring UI
Same Location on View
Anchoring UI elements allows Unity to scale objects to remain in the view for different size displays.
Click on the middle-center box-in-a-box icon to view the Anchor Presets.
Anchor Presets
Here is an anchor set at the top right, with Position (0, 0, 0):
Top right anchor
After drag and drop resizing, here is Score_Text at Position (-100, -50, 0):
Game view after anchor positioning
Adjusting Object size with changing screen
Next is to have Unity adjust object size according to smaller and larger screens.
Select (highlight) the Canvas in the Hierarchy. Note the components:
Render Mode: “Screen Space — Overlay” to use a layer on top of the Foreground and Background layers (over the main camera).
UI Scale Mode. Change from “Constant Pixel Size” to “Scale With Screen Size.” With a UI Text, this creates small text on small views, large text on large views.
Keeping Score
Highlight the “Score_Text” object in the Hierarchy, and a reference variable can point to the “Text” property of the “Text” component and include the string displayed on the Canvas.
Text property
Setting up the UI Manager
(a) Create an Empty object, named “UI_Manager” in the Hierarchy.
(b) Create a new C# script in the Project — Assets — Scripts named “UIManager.”
(c) Highlight the empty object, and drag the script into the object.
Name the script at the time of creation, not later.
Hookup
Double click to enter into the Visual Studio to begin creating variables and behavior hookup for the UI, such as a score to concatenate with “Score: “
The UI Manager handles the output, and some player input — like “Load.” the various gameObjects contain the variable inputs.
public class Player : MonoBehaviour
{
...
[SerializeField]
private int _score = 0;
...
public void AddTenToScore()
{
_score += 10;
}
}
That is the Player class. In the Enemy class score is incremented.
public class Enemy : MonoBehaviour
{
...
private void OnTriggerEnter2D(Collider2D other)
{
...
if (other.tag == "Laser")
{
...
Player player = other.transform.GetComponent();
if(player != null)
{
player.AddTenToScore();
}
...
}
}
Here the problem is to connect ‘A’ with ‘B’ after collision with ‘C’, and check to make certain the connection is valid:
public class Enemy : MonoBehaviour
{
...
private void OnTriggerEnter2D(Collider2D other)
{
...
if (other.tag == "Laser")
{
...
GameObject gamePlayer = GameObject.FindWithTag("Player");
if( gamePlayer != null )
{
Player playerScore = gamePlayer.transform.GetComponent();
if( playerScore != null )
{
playerScore.AddTenToScore();
}
...
}
Enemy gets hit, notifies Player.
public class Player : MonoBehaviour
{
[SerializeField]
private int _score = 0;
...
public void AddTenToScore()
{
_score += 10;
}
}
Property: Text, Component: Text, Child: Score_Text, Class: UM_Manager.
When working in Unity, the UI is accessed by the code library. “using UnityEngine.UI;”
using UnityEngine;
using UnityEngine.UI;
public class UIManager : MonoBehaviour
{
...
}
Now the names of UI properties appear in the Visual Studio tips:
UI property Text tip
Method One
Here is the Unity Inspector before the drag and drop:
Drag UI Score_Text to Inspector Script Variable
Highlight UI_Manager. Drag UI object Score_Text to UI_Manager (Script).
Method Two
Delete UI_Manager from the Hierarchy.
Highlight Canvas. Add Component “UI Manager” (with C# icon) to Canvas.
Add UI Manager (with C# Script icon) to Canvas
With Canvas highlighted, drag “Score_Text” to the Inspector — UI Manager (Script) — “Score Text”:
Drag to Canvas’ UI Manager Script
Score_Text (Text) in Script
So either way, the UI Manager (Script) has “Score_Text (Text)” in the Score Text property.
Score_Text (Text) in property box
Now the UI property can be accessed in the script, and the script can access a score variable from the outside class Player.
public class UIManager : MonoBehaviour
{
[SerializeField]
private Text _scoreText;
void Start()
{
_scoreText.text = "Score " + 40; // or variable from Player
}
}
Here is a runtime test to see if the “Score “ + 40; appears in the Inspector:
Runtime test with “Score 40”
Unity 2021 change from type Text to type TMP_Text
From the online training:
Starting with Unity 2021, TextMeshPro is now the default text system used in Unity. Use the Code sample below to see the changes needed to make from video to get this to work properly.
Take a look at the version change of the old type to the new type:
using System.Collections;
using System.Collection.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
public class UIManager : Monobehaviour
{
// [SerializeField] private Text _scoreText
[SerializeField] private TMP_Text _scoreText;
...
}
Making the UI Connection after ‘A’, ‘B’, and ‘C’
Here is the additional code starting with the updated Player.AddTenToScore(). See how (“Canvas”) is used.
public void AddTenToScore()
{
_score += 10;
_uIManager = GameObject.Find("Canvas").GetComponent();
if (_uIManager != null)
{
_uIManager.ChangeScore(_score);
}
}
}
Now take a look at the UIManager class:
public class UIManager : MonoBehaviour
{
[SerializeField]
private int _scoreNow;
public void ChangeScore( int _score )
{
_scoreNow = _score;
}
}
After some initialization in Start(), the UI makes adjustments when properties change value.
public class UIManager : MonoBehaviour
{
[SerializeField]
private Text _scoreText;
[SerializeField]
private int _scoreNow;
private int _scoreBefore;
void Start()
{
_scoreNow = 0;
_scoreBefore = 0;
// assign text comonent to the handle
_scoreText.text = "Score " + _scoreNow;
}
// Update is called once per frame
void Update()
{
if ( _scoreNow != _scoreBefore )
{
_scoreBefore = _scoreNow;
_scoreText.text = "Score " + _scoreNow;
}
}
From the Tutorial:
Alternative with Connection to gameObject Player
public void UpdateScore( int playerScore )
{
_scoreText.text = "Score: " + playerScore.ToString();
}
Optimization from Tutorial
Avoid “Player player = “ each time a hit is made. Move the reference creation to the moment of instantiation of the prefabs object “Enemy.”
public class Enemy : MonoBehaviour
{
...
private Player _player;
void Start()
{
_player = GameObject.Find("Player").GetComponent();
}
}
Now the “_player” can be used repeatedly.
private void OnTriggerEnter2D(Collider2D other)
{
...
if (other.tag == "Laser")
{
...
// GameObject gamePlayer = GameObject.FindWithTag("Player");
// if( gamePlayer != null )
// {
// Player playerScore = gamePlayer.transform.GetComponent();
// if( playerScore != null )
// {
// playerScore.AddScore();
// }
// }
if( _player )
{
_player.AddScore();
}
...
}
}
}
Now repeat with the UI connection to avoid multiple GetComponent calls:
public class Player : MonoBehaviour
{
...
private UIManager _uIManager;
void Start()
{
...
_uIManager = GameObject.Find("Canvas").GetComponent();
if ( _uIManager == null )
{
Debug.LogError("Canvas.UI_Manager is missing.");
}
}
...
public void AddScore(int points)
{
_score += points;
_uIManager.UpdateScore(_score);
}
}