The Singleton
Part of the Building Real Games section of Coddy's Unity journey. Lesson 13 of 56.
An Inspector reference needs something to drag onto. Enemies that a spawner makes during the game come from a prefab, and a prefab can only point at assets and at its own parts, never at an object in a scene, so their GameManager field is empty. The usual answer is a singleton: the GameManager stores itself in a field that every script can reach through the class name.
public class GameManager : MonoBehaviour
{
public static GameManager Instance;
private int kills;
void Awake()
{
Instance = this;
}
public void EnemyDown()
{
kills++;
Debug.Log("Kills: " + kills);
}
}// Enemy.cs, on the enemy prefab
public void Die()
{
GameManager.Instance.EnemyDown();
Destroy(gameObject);
}static means the field belongs to the class, not to an object. Each GameManager object would get its own kills, but there is only one Instance in the whole game, and you reach it with the class name: GameManager.Instance. Any script can read it, an enemy spawned a minute ago included, with no field of its own to fill in.
The manager sets Instance = this; in Awake, where this is the script itself. Unity runs every Awake in the scene before any Start, so other scripts can use GameManager.Instance from their Start on. A second GameManager in the scene would overwrite Instance with itself; the Scenes and Levels chapter shows how to stop that.
Challenge
EasyMeteors rain down. The Spawner drops a Meteor from a prefab every 1.5 seconds, the arrows move the Player, and the GameManager counts a catch with MeteorCaught() and a meteor that hits the ground with MeteorLanded(). Those scripts are ready.
The Meteor script reports through its game field, but the meteors come from a prefab, so game is empty and every report fails. Fix it with a singleton:
- In
GameManager.cs, add a public static fieldInstanceof type GameManager and set it to this script in Awake. - In
Meteor.cs, delete thegamefield and report throughGameManager.Instanceinstead.
Press Play, catch a few meteors and miss a few, then Check.
Try it yourself
using UnityEngine;
using TMPro;
public class GameManager : MonoBehaviour
{
public TMP_Text caughtText;
public TMP_Text shieldText;
private int caught;
private int shield = 3;
public void MeteorCaught()
{
caught++;
caughtText.text = "Caught: " + caught;
}
public void MeteorLanded()
{
shield--;
shieldText.text = "Shield: " + shield;
}
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Building Real Games
2Buttons and Screens
Buttons and onClickLambdasWiring in the InspectorPanels On and OffHealth BarsRecap: Upgrade Shop5Saving with PlayerPrefs
Save a NumberLoad with a DefaultHigh ScoreSave SettingsRecap: Coins in the Bank3The Game Manager
One Script Runs the GameThe SingletonGame StatesSwitching on the StateRecap: Round Manager6Project: Endless Runner
Three LanesObstacles Ahead9The New Input System
Two Input SystemsKeyboard and MousePressed This FrameInput ActionsRecap: Input Swap