Getting variables from other scripts

Yes, I am well aware that this question has been posted a lot. I have looked through so many of those forum posts and videos but not a single one seems to be working. I don’t know if it is because something maybe changed during the time, after all, some of the posts I looked at were from 10 years ago!

Anyways, I am trying to simply get a variable from another script to be used in this script. The point is that it’s a strategy game that needs to check if the player has enough resources to actually pay for the building being placed. I have it so it placed the building in one script, and have the resources being generated in another. But I need the building to check if there is enough money in the other script. This is the script that I gathered from previous forum posts:

int _money = gameObject.GetComponent<MoneyScript>().Money;

In VS it shows no errors, it used itellisense properly to give me the other script and the variable name. However, in game runtime it keeps throwing a NullReferenceException. Stating that “Object reference not set to an instance of an object” at the spot where the code is placed. The MoneyScript has Money set to public, and it is set to a value.

Nothing has changed in the past 10 years regarding this. The answer is simply that the GameObject this code is running on does not have a MoneyScript attached to it. GetComponent returns only components attached to the GameObject it was called on. You’re calling it with gameObject which is a property that points to the GameObject the current script is attached to.

Short answer - make sure both scripts are attached to the same GameObject in the scene for this method to work.

This is exactly what I was looking at and a source of the problem I encountered. Is there any way to get it to be used in a different GameObject? I am changing things right now to try to get it to work, but thanks.

Yes of course. There are many ways to do this. You need only to get a reference either directly to the target component, or to the GameObject that contains that component so you can call GetComponent.

The simplest is to declare a public field in your script. This will create a slot in the Unity Editor’s inspector and you can drag the other component into it in the Editor. This is explained in the manual. Search this page for “Accessing other objects”: https://docs.unity3d.com/Manual/ControllingGameObjectsComponents.html Don’t forget to actually drag the object into the field.

You can also use GameObject.Find(“hierarchy_name”).GetComponent().Money
Note: quotes for the name in the hierarchy, because it can contain spaces; no quotes for scriptName, as it cannot (it’s a variable name).
GameObject.Find is an expensive operation and not recommended. If you use it, only do it once and cache the reference in the script.

Thank you so much! I am making progress, if you don’t mind sticking around for one last question. I now have it so it correctly gets the amount of money from the other GameObject. The last thing that I need to do is update that script to now appear as less money. It gets it correctly, but doesn’t change it.
Again, thank you so much, it has been a real headache.

I was looking at that in the manual that Praetor sent. Thank you though.

What I would do is add a new function on your MoneyScript class like this:

public void SubtractMoney(int amount) {
  this.Money = this.Money - amount;
}

Then when you get the MoneyScript reference you can call that function! What that exactly looks like depends on how you did it though. Probably something like this:

// This is the thing you drag the object into in the inspector
public GameObject moneyObject;

// Then, later in your code when you want to subtract the money, probably inside some other function
MoneyScript ms = moneyObject.GetComponent<MoneyScript>();
int amountToSubtract = 5;
ms.SubtractMoney(amountToSubtract);
1 Like

Thank you again for all your help.

Using functions in the main script to manipulate the variables seems to be the preferred way, so you can pass the amount as an argument. I’d name it “changeMoney” instead of “subtractMoney”, so you can do any kind of operation on it. Keep the name more general, so it’s more flexible…you can use it to add money, etc. So (in another common scenario) instead of “takeDamage”, which implies a subtraction, it would be called “changeHealth”, which could be anything.

You can also change the value directly, without a function:
moneyObject.GetComponent().Money = moneyObject.GetComponent().Money - 10;

Basically,
moneyObject.GetComponent().
gets you access to that script, so you can change variables and run functions (they must be public). Cache the call in a local variable, like the “ms” used in the example, so the lookup only happens once.

I don’t think the “this” is needed, just “Money”. PraetorBlue, is there a reason you wrote it that way? Curious.

Not really, just to be explicit about the fact that we’re changing a member variable of the class. It’s kind of insurance against OP putting the function in the wrong place.

This way leads only to despair, which is why I didn’t mention it :smile:. In fact, OP would be better off if Money wasn’t public at all (or at least was a property so that MoneyScript has full control over it). But I didn’t want to get too deep into the rabbit hole in this thread.

1 Like

Yes and yes!