How do I update a UI Text element?

I need to update a text element that shows how many targets are left to destroy. Everything else up to that point in the code works as expected, that int gets decreased by 1 as expected, but for some reason when I convert the int to a string and add it as text to the label it doesn’t work and throws a “NullReferenceException: Object reference not set to an instance of an object”. Note that the issue is when it tries to write to the Text.text, not in the conversion - also I’ve removed some code that has nothing to do with it.

using UnityEngine;
using UnityEngine.UI;

public class StartButton : MonoBehaviour {

	public static bool isRunning = false;
	public static int numOfTargets = 10;

public Text targetName;
public Text timer;
public static Text targetsLeft;


	public static void UpdateTargetTotal(){
		numOfTargets--;
		if (numOfTargets > 1) {
			string test = numOfTargets.ToString();
			targetsLeft.text = test;
		}
		else {
			isRunning = false;
		}
	}
}

When I hit the target with a projectile, the target executes its own method which is as follows:

public class Target : MonoBehaviour {

	void OnCollisionEnter (Collision c){
		if (c.gameObject.tag == "Pellet"){
			Destroy (gameObject);
			StartButton.UpdateTargetTotal();
		}
	}
}

But the issue/exception comes in when it tries to execute the

targetsLeft.text = test;

line.

How is this solved? Is it an issue with the targetsLeft being a static variable?

Am I approaching this the entire wrong way? After some thought, I’ve considered that I’m doing it all wrong and I should be creating a new instance of the entire class when the player walks in to the trigger area. I’m going to make copy the project and try that while waiting for answers.

I’ve had this problem too when i just started learning UI, sometimes the UI elements were null without any reason, especially when going from scene to scene (even if UI elements were assigned as public from inspector). I still wasn’t able to find the problem for days, instead i rebuilt my implementation and never had that problem again.

  • I wouldn’t use static because it may update it even if object doesn’t exist. If you want it to live between scenes use DontDestroyOnLoad and remove manually when not needed (in lobby for example).
  • Create a static methods to get local instance or make static getInstance().
  • If, in the future collision will be not the only way to refresh the count, use delegates - events.

This method hides the instance.

public class StartButton : MonoBehaviour {

 private static StartButton instance;
 public int targets = 10;
 public Text targetCount;

 //lazy initialization
 private void Awake(){
     instance = this;
 }

 //call when want to update
 //you might want to check the instance for null
 public static void updateCount(){
     instance.recount();
 }

 private void recount(){
     targets --;

     targetCount.text = targets.ToString();
 }

}

targetsLeft.text = test;

should be

targetName.text = "text";