The Singleton
Part of the Building Real Games section of Coddy's Unity journey. Lesson 13 of 60.
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
EasyLet the meteors reach the GameManager through a singleton.
- In
GameManager.cs, addpublic static GameManager Instance;and anAwake()withInstance = this;. - In
Meteor.cs, delete thegamefield and callGameManager.Instance.MeteorLanded()andGameManager.Instance.MeteorCaught()instead.
Press Play and catch a meteor: Caught: 1 shows, with no errors in the Console. 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;
}
}
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 SwapPractice on your own: Unity playground