Saving and displaying ints in different scenes

So I have a script that counts how many minutes you spend in the current session. That part works fine, but I want to display it on a different scene that you go to when the level is finished. Also, I want to hide the original minute counter and replace it with another text object that displays your time. Instead of those last 2 ideas working, I am met with an object reference error:

NullReferenceException: Object reference not set to an instance of an object
minutesscounter.HideUI (TMPro.TMP_Text text) (at Assets/Scripts/minutesscounter.cs:59)
minutesscounter.Update () (at Assets/Scripts/minutesscounter.cs:51)

Heres my code:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using UnityEngine.SceneManagement;

public class minutesscounter : MonoBehaviour
{
    int minutes1 = 0;
    public TMP_Text uiText2;
    private bool isVisible = true;
    TMP_Text text = null;
    int minutes = 0;
    public TMP_Text uiText;

    void Start()
    {
        text = gameObject.GetComponent<TMP_Text>();
        StartCoroutine(minutecounter());
    }

    IEnumerator minutecounter()
    {
        while (minutes < 100000) //Counts the minutes
        {
            yield return new WaitForSeconds(60);
            minutes = minutes + 1;
        }
    }

    void Update()
    {
        uiText.SetText(minutes + " minutes".ToString()); //Display on screen
        if (Input.GetKeyDown(KeyCode.N))
        {
            if (isVisible)
            {
                HideUI(text);
                isVisible = false;
            }
            else
            {
                ShowUI(text);
                isVisible = true;
            }
        }
        if (SceneManager.GetActiveScene () == SceneManager.GetSceneByName ("level1time")) //Hide this when the scene goes to "level1time"
        {
            minutes1 = minutes;
            HideUI(text);
            uiText2.SetText(minutes1 + " minutes".ToString());
            Debug.Log("it works!");
        }
    }

    public static void HideUI(TMP_Text text) //Hide the UI on command
    {
        text.transform.localScale = new Vector3(0, 0, 0);
    }

    public static void ShowUI(TMP_Text text) //Re-show the UI on command
    {
        text.transform.localScale = new Vector3(1, 1, 1);
    }
}

Any help is greatly appreciated :slight_smile:

Doesn’t really matter what you’re trying to do, but thank you for being thorough in your description.

The reason it does not matter is that the answer is always the same for Null Reference… ALWAYS.

It is the single most common error ever.

Don’t waste your life spinning around and round on this error. Instead, learn how to fix it fast… it’s EASY!!

Some notes on how to fix a NullReferenceException error in Unity3D

  • also known as: Unassigned Reference Exception
  • also known as: Missing Reference Exception
  • also known as: Object reference not set to an instance of an object

http://plbm.com/?p=221

The basic steps outlined above are:

  • Identify what is null
  • Identify why it is null
  • Fix that.

Expect to see this error a LOT. It’s easily the most common thing to do when working. Learn how to fix it rapidly. It’s easy. See the above link for more tips.

This is the kind of mindset and thinking process you need to bring to this problem:

Step by step, break it down, find the problem.

Thanks for the help! After nearly an hour, I found that the error was me incorrectly grabbing a text component - which now works.

1 Like

So I’ve encountered some weird problems. For some reason, the integer I use to count the minutes is just randomly going up and down. Another problem is the text doesn’t display the correct integer number.

7097329--845620--upload_2021-5-1_10-0-1.png

Heres my code:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
using UnityEngine.SceneManagement;

public class minutesscounter : MonoBehaviour
{
    bool textupdate = true;
    TMP_Text text2 = null;
    int minutes1 = 0;
    public TMP_Text uiText2;
    private bool isVisible = true;
    TMP_Text text = null;
    int minutes = 0;
    public TMP_Text uiText;

    void Start()
    {
        text = uiText.GetComponent<TMP_Text>();
        StartCoroutine(minutecounter());
    }

    IEnumerator minutecounter()
    {
        while (minutes < 100000) //Counts the minutes
        {
            yield return new WaitForSeconds(60);
            minutes = minutes + 1;
        }
    }

    void Update()
    {
        uiText.SetText(minutes + " minutes".ToString()); //Display on screen
        if (Input.GetKeyDown(KeyCode.N))
        {
            if (isVisible)
            {
                HideUI(text);
                isVisible = false;
            }
            else
            {
                ShowUI(text);
                isVisible = true;
            }
        }
        if (SceneManager.GetActiveScene () == SceneManager.GetSceneByName ("level1time")) //Hide this when the scene goes to "level1time"
        {
            if (Input.GetKeyDown(KeyCode.N))
            {
                HideUI(text);
            }
            if (isVisible)
            {
                HideUI(text);
            }

            if (textupdate = true)
            {
                minutes1 = minutes;
                uiText2.SetText(minutes1 + " minutes".ToString());
                Debug.Log(minutes1);
                textupdate = false;
            }
        }
    }

    public static void HideUI(TMP_Text text) //Hide the UI on command
    {
        text.transform.localScale = new Vector3(0, 0, 0);
    }

    public static void ShowUI(TMP_Text text) //Re-show the UI on command
    {
        text.transform.localScale = new Vector3(1, 1, 1);
    }
}

That’s a pretty complicated way to count minutes… I can’t even reason about if it would be correct or not.

I would start with a float variable:

private float timeElapsed;

And then in your Update():

timeElapsed += Time.deltaTime;
int minutes = (int)(timeElapsed / 60);

DONE.

Well the minute counter itself works, just the text won’t display the integer, and the integer itself keeps changing between 1 and 0.

I don’t think it’s the problem, but this seems … odd:

Don’t you want the expression to be a more standard format expression such as:

var s = minutes.ToString("0") + " minutes";

or perhaps

var s = System.String.Format( "{0:0} minutes", minutes);

? (obviously pass that into SetText())

Is it really working? What happens if right before your string expression you say minutes = 123; ??

Do you see 123? Or do you see 1 / 0.

ALSO, this is bad:

Setting scales to zero causes problems with UI Layout components and could throw divide by zero exceptions.

Just disable it by changing the text’s .enabled field to false / true.

ALSO, I don’t think you can compare actual Scene objects like you are doing on line 50. The reason: they are value types (structs) so each Scene is a new copy of the master list of scenes. Maybe it will work, but I would suggest a different way of identifying a scene that doesn’t rely so much on the name not changing.

So now I’m confused. Changing minutes to equal 123 displays “123 minutes”, while changing it back to minutes1 = minutes displays “0 minutes” along with the int changing like this:

7097689--845683--upload_2021-5-1_12-39-13.png

Then the counter isn’t working.

The code you have is way too complicated for a counter, and I am a simple man, I cannot reason about such things.

I recommend the approach I wrote above.

The reason: I have counted more than a few things in my time hacking games.