Skip to main content

🔢 Lesson 6.2: A Live Score Counter

Now we connect the pieces: collecting an item adds a point, and a GameManager keeps the total and updates the on-screen text. This is the moment your game starts to feel like a game.

🎯 Learning Objectives

  • Create a GameManager to hold the score
  • Update a TextMeshPro label from code
  • Reference the GameManager from the collectible to add points
  • Understand a simple way for scripts to talk to each other

Estimated Time: 40 minutes

In This Lesson

The Goal

Every time the player collects a star, the score ticks up and the HUD shows the new total — live:

A real Unity render of the game with a live score reading Score: 3 in the corner. ⭐ Score: 3
Figure 1: A live score over a real render. Collect a star → this number goes up.

The GameManager

A GameManager is a single object that owns game-wide data like the score. Create an empty GameObject named GameManager and attach this script:

using UnityEngine;
using TMPro;               // needed for TextMeshPro

public class GameManager : MonoBehaviour
{
    public TMP_Text scoreText;   // drag the HUD text here in the Inspector
    private int score = 0;

    void Start()
    {
        UpdateScoreText();
    }

    public void AddPoint()
    {
        score = score + 1;
        UpdateScoreText();
    }

    void UpdateScoreText()
    {
        scoreText.text = "Score: " + score;
    }
}
  • using TMPro; unlocks the TextMeshPro types.
  • public TMP_Text scoreText; is a slot — drag your HUD text object into it in the Inspector.
  • AddPoint() is public so the collectible can call it.

Wiring the Collectible

Update the Collectible script from Lesson 5.4 so that, on pickup, it finds the GameManager and adds a point:

void OnTriggerEnter(Collider other)
{
    if (other.CompareTag("Player"))
    {
        // find the GameManager in the scene and score a point
        GameManager gm = FindObjectOfType<GameManager>();
        if (gm != null) gm.AddPoint();

        Destroy(gameObject);
    }
}

Now: player touches star → collectible calls gm.AddPoint() → score increases → HUD text updates. Wire the text once (drag the HUD text into the GameManager's Score Text slot) and it all flows.

How Scripts Talk to Each Other

graph LR A[Collectible
OnTriggerEnter] -->|calls| B[GameManager.AddPoint] B -->|updates| C[TMP_Text on the HUD]

We used FindObjectOfType<GameManager>() — a simple way for one script to grab another. It's perfect for learning. As projects grow you'll meet tidier patterns (like a singleton), but don't worry about that yet.

⚠️ NullReferenceException on scoreText?

You forgot to drag the HUD text object into the GameManager's Score Text slot. An empty slot means scoreText is nothing, and scoreText.text = ... throws. Drag it in.

Hands-on Exercise

🏋️ Exercise: Make it count

  1. Add a HUD text (Lesson 6.1) reading Score: 0.
  2. Create a GameManager object with the script; drag the HUD text into its Score Text slot.
  3. Update your Collectible to call AddPoint() on pickup.
  4. Play, collect a few stars, and watch the score climb.
💡 Score doesn't change

Check: the HUD text is dragged into the GameManager slot; the collectible actually collects (three-must-haves from Lesson 5.4); and there's exactly one GameManager in the scene.

✅ Bonus: a win message

Add a total-stars count. When score reaches it, set the HUD text to "You win!". (We formalize win/lose in Module 7.)

🎯 Quick Quiz

Question 1: Why is AddPoint() marked public?

Question 2: What must you drag into the GameManager's Score Text slot?

Summary

🎉 Key Takeaways

  • A GameManager holds game-wide data like the score.
  • Update UI from code via a TMP_Text reference and scoreText.text = ... (remember using TMPro;).
  • A collectible calls gm.AddPoint() on pickup; wire the text slot in the Inspector.
  • FindObjectOfType<GameManager>() is a simple way for scripts to find each other.

🚀 What's Next?

Numbers going up is good; a satisfying ding when it happens is better. Lesson 6.3 adds sound effects and music.

🎉 It keeps score!