Skip to main content

Stage 4: Gold and the HUD

Course progressStage 4 of 10
~45 min
Build

a gold counter, a passive gold trickle, and an on-screen readout

Learn

how one shared GameManager holds the game's numbers, and how UI Text shows them

Ship

a gold total that ticks up while you watch

The big idea

Towers cost something to place. In Castle Defense that something is gold. Before the player can spend gold, the game needs one trusted place that knows how much gold there is — not the tiles, not the slimes, one central object everyone agrees on.

That object is a GameManager. It's a single GameObject whose script holds the game's shared numbers. The problem: lots of other scripts will need to reach it. We don't want every tile hunting around the Scene for the manager. So we make the manager findable from anywhere using a static field called instance — a variable that belongs to the class itself, not to any one copy. Any script can write GameManager.instance.gold and reach the one and only manager. A class set up to have exactly one shared copy like this is called a singleton.

The player also needs to see the gold. We draw it with a Canvas — the special object that holds all on-screen interface — and a UI Text element on it. When the number changes, the manager updates the text. And to make the total grow on its own, we'll use InvokeRepeating (from Stage 2) to add a little gold every couple of seconds.

New words
Canvas
The GameObject that holds all your on-screen interface. UI elements like text and buttons live as children of a Canvas.
UI Text
A text element that draws words on the Canvas. We use the Legacy Text so there's nothing extra to import.
static
A field or method that belongs to the class itself instead of to one copy. There's exactly one, shared by everyone.
singleton / instance
A class set up to have exactly one shared copy. We store it in a static field named instance so any script can reach it.
InvokeRepeating
The Unity timer from Stage 2. Here it calls our Trickle method every couple of seconds to add gold.
Before you start

Finish Stage 3: The Grid Board — you have a clickable board of tiles. This stage adds the gold the player will eventually spend on those tiles.

Build it

Step 1 — Add the GameManager object

The manager is invisible — it has no sprite. It's just an empty GameObject that runs the GameManager script.

Build this GameObject

GameManager

Empty GameObject
Open recipe
Position
(0, 0, 0)
Components to add
  • GameManager.cs (added in Step 2)

Create one and only one. The whole point of the singleton is that there's a single GameManager — making two would break the shared instance.

Step 2 — Write the GameManager, pass by pass

Select the GameManager, Add Component → New Script, name it GameManager, and build it in three passes.

Pass 1 — prove the singleton. First we set up the shared instance and confirm it holds the starting gold:

using UnityEngine;

public class GameManager : MonoBehaviour
{
public static GameManager instance;
public int gold = 50;

void Awake()
{
instance = this;
}

void Start()
{
Debug.Log("Gold: " + gold);
}
}

Press Play. The Console prints Gold: 50. Awake runs before Start and sets instance = this, so the manager registers itself the instant the game begins. Any other script can now reach it through GameManager.instance. Stop.

Pass 3 needs UI, so build the HUD now. Add a Canvas with a gold readout, then we'll wire it up.

Build this GameObject

Canvas

UI Canvas
Open recipe
Created via
GameObject → UI → Canvas
Components to add
  • Canvas
  • Canvas Scaler
  • Graphic Raycaster

Unity adds an EventSystem object too — leave it. The Canvas draws on top of the game world in screen space.

Build this GameObject

Gold Text

UI Text (Legacy)
Open recipe
Parent
Canvas
Created via
GameObject → UI → Legacy → Text
Text
Gold: 50 (placeholder)
Anchor
top-left, so it sits in a corner
Components to add
  • Text (Legacy)

Use the Legacy Text on purpose — it needs no extra package import, unlike TextMeshPro. Drag it to a top corner of the Canvas so it reads as a HUD.

Pass 2 — show the gold and let it change. Now we connect the manager to the text. Add a goldText field, an AddGold method, and an UpdateUI method:

using UnityEngine;
using UnityEngine.UI;

public class GameManager : MonoBehaviour
{
public static GameManager instance;
public int gold = 50;
public Text goldText;

void Awake()
{
instance = this;
}

void Start()
{
UpdateUI();
AddGold(25);
}

public void AddGold(int amount)
{
gold += amount;
UpdateUI();
}

void UpdateUI()
{
if (goldText) goldText.text = "Gold: " + gold;
}
}

Save, return to Unity, select the GameManager, and drag your Gold Text object from the Hierarchy into the manager's Gold Text field. Press Play. The readout shows Gold: 50, then jumps to Gold: 75 because Start calls AddGold(25) once. That proves the manager can change a number and the screen follows. Remove that test AddGold(25) line before the next pass. Stop.

Pass 3 — trickle gold and add spending. A real economy grows over time and lets the player spend. We add the trickle on a timer and a SpendGold method the next stage will use:

Script anatomy

The full script, line by line

The finished Stage 4 manager: a shared singleton that holds gold, shows it, trickles it up, and can be asked to spend.

using UnityEngine;
using UnityEngine.UI;

public class GameManager : MonoBehaviour
{
public static GameManager instance;
public int gold = 50;
public Text goldText;

void Awake()
{
instance = this;
}

void Start()
{
UpdateUI();
InvokeRepeating(nameof(Trickle), 2f, 2f);
}

void Trickle()
{
AddGold(5);
}

public void AddGold(int amount)
{
gold += amount;
UpdateUI();
}

public bool SpendGold(int amount)
{
if (gold < amount) return false;
gold -= amount;
UpdateUI();
return true;
}

void UpdateUI()
{
if (goldText) goldText.text = "Gold: " + gold;
}
}
  1. Lines 6–8The shared state

    instance is the static handle every other script uses to find this manager. gold is the number that matters. goldText is the readout, wired in the Inspector.

  2. Lines 10–13Awake registers the singleton

    Awake runs before any Start in the Scene, so the manager is reachable through GameManager.instance before other scripts wake up and look for it.

  3. Lines 17–18The trickle timer

    InvokeRepeating waits 2 seconds, then calls Trickle every 2 seconds. Trickle just adds 5 gold, giving the player a slow, steady income even before they earn from defeating enemies.

  4. Lines 31–37SpendGold returns true or false

    It checks if there's enough gold first. Not enough? Return false and change nothing. Enough? Subtract, refresh the readout, return true. Stage 5's tower placement will call this and only build if it gets true back.

  5. Lines 40–42One place updates the screen

    Every method that touches gold ends by calling UpdateUI, so the readout is never stale. The 'if (goldText)' guard keeps it from erroring if the field isn't wired yet.

Press Play and watch the readout. It starts at Gold: 50 and climbs by 5 every two seconds — gold you can see accumulating without touching anything.

Understand it

The singleton pattern solves a real problem: dozens of objects need the same shared numbers, and you don't want them passing references around or searching the Scene. By storing the manager in a static instance field set in Awake, any script reaches it instantly with GameManager.instance. The cost is discipline — there must be exactly one GameManager, or instance ends up pointing at whichever one woke up last. For a single-scene camp game that's an easy rule to keep.

SpendGold returning a bool is a small but important design choice. Instead of the tower code checking the gold, subtracting it, and updating the screen itself, it asks the manager one question: "can I afford this?" The manager owns the answer and does the bookkeeping. That keeps all gold logic in one file, so when you later add costs or refunds, you change one method instead of hunting through every script that touches money.

Try this

Learning beat

Try this

Three short experiments. Predict before you run, then test your guess.

Predict first

Change the trickle from AddGold(5) to AddGold(20) and the interval to 1f, 1f. Before pressing Play, predict the readout's value after ten seconds. Run it and check your math against the screen.

Compare

Temporarily delete the if (goldText) guard in UpdateUI, unassign the Gold Text field, and press Play. You'll get a red error. Put the guard back. Compare the two: why is a guard against an unwired reference worth the extra line?

Connect

SpendGold already returns true or false, but nothing calls it yet. In Stage 5, clicking a tile will try to buy a tower. How would the tile use the true/false answer to decide whether to actually build?

Test your stage

  • In Pass 1, the Console printed Gold: 50.
  • The Gold Text is a child of the Canvas and is dragged into the GameManager's Gold Text field.
  • Pressing Play shows the readout starting at 50 and climbing by 5 every two seconds.
  • There is exactly one GameManager object in the Scene.
  • Design check. Watch the gold trickle for thirty seconds. Does income arrive fast enough to feel rewarding, but slow enough that the player has to choose carefully? Pick a trickle amount and interval that make spending feel like a real decision.

If it breaks

  • The readout never changes, or shows the placeholder forever. The Gold Text field on the GameManager is probably empty. Select the GameManager and drag your Gold Text object into it.
  • A red "NullReferenceException" mentioning goldText. The field is unwired and you removed the if (goldText) guard. Either wire the field or keep the guard.
  • The text doesn't appear on screen at all. It may be positioned off the Canvas, or its color matches the background. Select the Gold Text, set its anchor to a corner, reset its position, and give it a readable color.
  • "The name 'Text' could not be found" compile error. You're missing using UnityEngine.UI; at the top of the script. Legacy UI Text lives in that namespace.
  • Two managers, weird behavior. If you duplicated the GameManager, instance points at whichever woke last. Keep exactly one GameManager in the Scene.