This article is Part 1 in a 25-Part Series.

Single(ton) Sole Survivor

The first thing we need to create is a GameObject which will hold information throughout the entire game play.

Start a new Unity Project selecting 2D. Start by creating an empty Game Object naming it MasterTracker.

As the MasterTracker GameObject is to hold information that is required in all scenes, it should not be destroyed when moved from Scene to Scene. To do this, we will need to create a script component also called MasterTracker to store the information. For the MasterTracker to persist in every scene, we will need to create a singleton pattern in the script.

The rationale is to create a singleton is to ensure each scene only contains one MasterTracker GameObject(which holds the script MasterTracker to store information required to move from scene to scene), and it will be the same instance that ran on the first scene on every scene.

We will be placing a MasterTracker GameObject in every scene, this is to ensure that game will not break if we start on an alternate scene other than the first one.

So the MasterTracker script contains a DontDestroyOnLoad to prevent the MasterTracker GameObject from getting destroyed while moving from scene to scene. The first time the MasterTracker GameObject runs, it stores itself into a static variable (which we will call Instance). Then on next scene, the MasterTracker GameObject(which every scene has one) already in the scene will run and check if the static variable Instance already contains an instance of MasterTracker. If there is already one, it will destroy itself leaving the only one MasterTracker GameObject (which is loaded from the previous scene) in the scene. Code will be as below.

To understand more of Singleton and Static, I suggest seeing this youtube video. I believe this is the best illustration to explain the concept.

static MasterTracker instance=null;

void Awake()
{
    if(instance == null)
    {
        DontDestroyOnLoad(gameObject);
        instance = this;
    }else if(instance != this)
    {
        Destroy(gameObject);
    }
}

Now, reset the transform for the MasterTracker, so it is set at position origin.(optional but good practice for housekeeping)

By now you should have two GameObjects in your Hierarchy. The MasterTracker and Main Camera. Your Hierarchy and Inspector for MasterTracker should look like this.

Now we need to determine what is the information that needs to persist inter-scene. If you did a playthrough on Battle City, you would notice that after every stage, it will load a scene to tabulate the score earned from the previous stage. So take a look at the below to determine what needs to be retained scene to scene.

From the Score scene we will need to hold information for Player Score, number of Tanks destroyed per type, the points each tank is worth, and the stage number. In additional we also need to hold information of the player lives left. So let’s create Static Public Variables for these.

public static int smallTankDestroyed, fastTankDestroyed, bigTankDestroyed, armoredTankDestroyed;
public static int stageNumber;
public static int playerLives=3;
public static int playerScore = 0;

As for the points each tank is worth, we will create a private variable with SerializedField and public get variable each as this will allow us to change the points worth for each type of tank from Inspector and yet allow other GameObjects to access it without changing it. Example will be like below.

[SerializeField]
int smallTankPoints = 100;
public int smallTankPointsWorth { get { return smallTankPoints; } }

So this concludes the setup of the MasterTracker which is the most important part to ensure there is continuity in the game. We might be revisiting this script to add on if we noticed something that needs to persist between scenes. We will discussing on how to create a template for Game Scene using Tilemap in the next post. The full code up till now will be as below.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MasterTracker : MonoBehaviour {

    static MasterTracker instance=null;

    [SerializeField]
    int smallTankPoints = 100, fastTankPoints = 200, bigTankPoints= 300, armoredTankPoints=400;
    public int smallTankPointsWorth { get { return smallTankPoints; } }
    public int fastTankPointsWorth { get { return fastTankPoints; } }
    public int bigTankPointsWorth { get { return bigTankPoints; } }
    public int armoredTankPointsWorth { get { return armoredTankPoints; } }

    public static int smallTankDestroyed, fastTankDestroyed, bigTankDestroyed, armoredTankDestroyed;
    public static int stageNumber;
    public static int playerScore = 0;
  
    void Awake()
    {
        if(instance == null)
        {
            DontDestroyOnLoad(gameObject);
            instance = this;
        }else if(instance != this)
        {
            Destroy(gameObject);
        }
    }
}

This article is Part 1 in a 25-Part Series.