Change TextMeshPro Text from script that is NOT attached to it

Hey guys,

I’m absolutely pulling my hair out on this one. My new project was going so well and I did really learn new stuff while coding. But this simple problem is unfixable for me. I have very little free time and I use it for my project. It frustrates me, that it now took me 2 days and I got 0 progress while wasting 100% of my time on this one.

So I have got a player object which consists of a sphere. It has children (my main camera and my gun). The gun has an attached script. In this script, I manage shooting and magazine counting. I want the player to see how much bullets are left, so I created a TextMeshPro. It was added to my Canvas, which also holds other UI-objects (and also other TextMeshPros). Now the problem is, that I want to change the text of the TextMeshPro in the gun script.

Simplest solution: create “public TextMeshPro textMesh”. Drag the TextMeshPro object to the script in the inspector and youre good to go. Well as you can guess, this doesnt work. Unity just wont let me add it.

So I thought that I could name the Text to “magLabel”. Now I tried going

Text text = GameObject.Find("magLabel").getComponent<Text>
text = bulletsLeft;

This just throws a NullReferenceException even though the Game object exists.

I also tried

TextMeshPro textMesh = GameObject.Find("magLabel");
textMesh.text = bulletLeft;

And some other things. Nothing works. I’m frustrated enough to just stop learning Unity at this point.

Can ANYONE find a solution to this problem?

What you did may be the simplest solution, but you shouldn’t make it public. Put [SerializeField] in place of public in your script. If it has to be set from another script, make a setter method for doing that.

The script you want to have it in is a script you have created that implements the Singleton Pattern, which is your script that will be present throughout your game. In my latest one that was my GameStatus script.

Be sure to use a private void Awake() method where you destroy any new objects of that type, so only the original version stays around. Something like this (you can see how I am using it to show my score, which is a TextMeshPro object):

public class GameStatus : MonoBehaviour
{
[SerializeField]
TextMeshProUGUI score;
[SerializeField]
int currentScore = 0;

private void Awake()
{
	int gameStatusCount = FindObjectsOfType<GameStatus>().Length;
	if (gameStatusCount > 1)
	{   // We only want to keep the first one to preserve game status between scenes
		gameObject.SetActive(false);    // Prevent anything from being able to find or interact with this instance of GameStatus
		Destroy(gameObject);    // Destroy this secondary version of GameStatus
		score.text = "Score:

" + currentScore.ToString();
} // if
else
{ // Tell Unity not to destroy this gameObject when another scene loads in the future
DontDestroyOnLoad(gameObject);
} // else
} // Awake()

public void DisplayScore()
{
	score.text = "Score:

" + currentScore.ToString();
} // DisplayScore()
} // class GameStatus

This explains why you want to use Awake() for this code: Unity - Manual: Order of execution for event functions

I hope that helps you.

Hello @DasHouse , I’m quite late but I had the same problem as yours but I figured it out with the help of one of the Unity tutorials (it’s not straight forward but it’s the process that we need).

Since you are using TextMeshPro too here is what I have done:

So at the top under using UnityEngine; add using TMPro;
Then create a public variable - public TextMeshProUGUI ur variable name
You should REMOVE the 177988-script.png

Hopefully, now you will be able to add the test to the script in the inspector.

The tutorial that I used is this: Roll-a-Ball: 7.3 Display the count value - YouTube