UI Elements controlled from a single class

Hi All,

Wanted to show the approach I have taken to handle all my UI elements within a single script.
To achieve this I created the below GameSession that covers Score, Health + Bombs and Lives that I intend to flesh out later:

public class GameSession : MonoBehaviour
{
    // Config Params
    [SerializeField] TextMeshProUGUI scoreText;
    [SerializeField] TextMeshProUGUI bombsText;
    [SerializeField] TextMeshProUGUI healthText;
    [SerializeField] TextMeshProUGUI livesText;

    // State variables
    int currentScore = 0;
    [SerializeField] public int currentLives = 2;
    [SerializeField] public int currentBombs = 0;
    int currentHealth;


    void Awake()
    {
        SetUpSingleton();
    }

    private void SetUpSingleton()
    {
        int numberGameSessions = FindObjectsOfType(GetType()).Length;
        if (numberGameSessions > 1)
        {
            Destroy(gameObject);
        }
        else
        {
            DontDestroyOnLoad(gameObject);
        }

        scoreText.text = currentScore.ToString();
        bombsText.text = currentBombs.ToString();
        livesText.text = currentLives.ToString();
        healthText.text = currentHealth.ToString();
    }
    
    public int GetScore()
    {
        return currentScore;
    }
    
    public void AddToScore(int scoreValue)
    {
        currentScore += scoreValue;
        if(currentScore > 0)
        {
            scoreText.SetText(currentScore.ToString("#,#"));
        }
        else
        {
            scoreText.SetText(currentScore.ToString());
        }
    }

    public void GetHealth(int health)
    {
        currentHealth = health;
        healthText.SetText(currentHealth.ToString());
    }

    public void GetBombs(int bombValue)
    {
        currentBombs += bombValue;
        bombsText.SetText(currentBombs.ToString());
    }


    public void GetLives(int livesValue)
    {
        currentLives += livesValue;
        bombsText.SetText(currentLives.ToString());
    }

    public void ResetGame()
    {
        Destroy(gameObject);
    }
}

Within my Enemy.cs I modify the score upon enemy death:

[SerializeField] int scoreValue = 50;
...
    void Start()
    {
        gameSession = FindObjectOfType<GameSession>();
    }

    private void Die()
    {
        GameObject explosion = Instantiate(deathVFX, transform.position, Quaternion.identity) as GameObject;
        soundManager.TriggerEnemyDeadSFX();
        Destroy(explosion, explosionDuration);
        Destroy(gameObject);
        gameSession.AddToScore(scoreValue);
    }

Similarly I modify the health from Player.cs following a hit:

    private void ProcessHit(DamageDealer damageDealer)
    {
        health -= damageDealer.GetDamage();
        damageDealer.Hit();
        gameSession.GetHealth(health);

        if (health <= 0)
        {
            Die();
        }
    }

Then finally on my SceneLoader.cs I added a couple IF statements to handle a NULL exception that occurred when navigating from the Start Menu before the GameSession.cs had been instantiated:

    public void LoadStartMenu()
    {
        SceneManager.LoadScene("Start Menu");
        if (FindObjectsOfType<GameSession>().Length == 1)
        {
            FindObjectOfType<GameSession>().ResetGame();
        }
    }

    public void LoadGame()
    {
        SceneManager.LoadScene("Game");
        if(FindObjectsOfType<GameSession>().Length == 1)
        {
            FindObjectOfType<GameSession>().ResetGame();
        }
        
    }

Hopefully this is useful for anyone looking to do similar.

The one part I haven’t quite worked the kinks out for is the transition to the Game Over scene.
Sticking with the prefab approach across scenes I end up displaying all UI elements on Game Over when I’m only interested in the score.
Unpacking the prefab to delete some of the elements dissociates the Game and Game Over instances resulting on the Game Over UI displaying zero values.
Open to any suggestions!

Privacy & Terms