Accessing variables from various object's scripts

Hi there, i’m having a problem with multi scripts variable access.

Explaining pratically:

I have one GUITexture and one object in my scene, let’s call the GUITexture “Button” and the object “Bridge”.
In my Bridge object i have a script (called BridgeControl) that controls the obj’s animation, and assign a state to a boolean variable, in this case, the checkStatus var, and it changes from false to true when the bridge is open, else, if the bridge is closed, it’s false.
Now, in my Button gui, i want to access the checkStatus var from the BridgeControl script in the other object, and, say, print “The bridge is open” if the checkStatus=true, or “The bridge is closed” if checkStatus=false…that’s it.

I tried with GameObject.GetComponent, but it only refers to the GameObject in which there is the script i want to access with GetComponent.

Any clue on how to do this?
Thanks in advance

For variables just prefix the variable name with :

TheNameOfTheScriptItsIn.NameOfVariable

so…

Script 1 called “Bridge.js” with variable called “checkMe”

Script 2 called “AssessDamage.js” uses the variable “checkMe” thus:

If(Bridge.checkMe == 1) {do whatever}

:slight_smile:

GameObject is the abstract class, not bound to any specific object. gameObject is the name of the instance variable used throughout Unity. Capitalization is important and the case for many other classes/variables in Unity.

To access a script you’ll need a reference to the game object. There are two ways to get it:

  • Create a variable in the script you want to access the game object from and then drag the game object onto the variable in the Unity editor.
  • Use GameObject.Find(“name”) to look for the game object by name.

Anyway, you’ll end up with a variable holding the reference to the game object and then you can do:
var script = refvar.GetComponent(ScriptType);

Hi again, thanks for replies. Still having problems, here i post the script:

var ponteControl : GameObject;

function Start()
{
	ponteControl = GameObject.Find("Ponte_Previz1");
	var ponteCheck = ponteControl.GetComponent(Anim_Ponte);
}

function Update()
{
	if (ponteCheck != null)
	{ print ("lol");}
	else { print ( "uff" );}
}

It returns BCE0005: Unknown identifier: ‘ponteCheck’.
Did a nullcheck and ponteControl is ok, and “Anim_Ponte” is the name of the script i want to access from that one.

Any help?

You’re declaring ponteCheck as a local variable in the Start function, so it doesn’t exist outside it.

–Eric

I’d like to jump in on this thread as well, as I’m having some trouble with inter-Script communication as well.

To jump in and expand on some of the answers for Akabane:

If you look at the tutorials, there are several similar solutions to your problem, and all of them are related to caching a link between the scripts.

The two methods described above go as follows: (Here I will use the example of looking for a variable in a script called LevelStatus from a script called PlayerStatus.)

Make a variable to an object that you set in the inspector:

PlayerStatus.js

var levelStatus : LevelStatus;


function Start () {
	if (levelStatus == null)
		Debug.Log("Player Status Start: No link to Level Status");

Here you’ve set up an exposed variable that will appear in the inspector, and you can drop the gameObject that contains your LevelStatus script on it.

In this case, your Level Attributes gameObject contains the script LevelStatus. Drag the gameObject Level Attribute onto the empty variable slot in Player Status. This will set the link.

In this case, the function Start() and Debug.Log are there to make sure you’ve not made an error.

The advantage to this method is that you do not need to know what you are looking for at the time you are writing the script - you’ve simply made a place holder. Another advantage is that if you change your choice of components, you can simply drag a new object onto that variable slot.

The drawback to this method, is there are ways that you can break this connection and the PlayerStatus.levelStatus resets to “null” or nothing, empty, etc… At this point you must reattach the script by hand.

The other method is contained completely within the code of the scripts.

PlayerStatus.js

private var levelStatus : LevelStatus;


function Start () {
	levelStatus = FindObjectOfType(LevelStatus);
	if (levelStatus == null)
		Debug.Log("Player Status Start: No link to Level Status");

In this case, you are setting a PRIVATE variable - it will not be expose in the inspector - and you are actually using the function Start() to do something. You are asking it to go and find the object you want while initializing the script, and caching it without your help.

The drawback to this method, is that you must know what you are looking for at the time you are writing your script, and if the component you want changes, you will have to re-write your code.

Now - the clarification that I need is around the second scripting method.

I’ve been “kit bashing” some scripts as a way to learn scripting and I’ve noticed in the tutorials that there are different ways to find that script to cache.

Example.js

private var levelStatus : LevelStatus;

function Start() {

//	One of the following:

	levelStatus = FindObjectOfType(LevelStatus);

	levelStatus = GetComponent(LevelStatus);

These are the two most common methods (I believe one is from the 2D Platformer [Gravek?] and the other from the 3rd Person tut [Unity?]…)

From scanning the docs, there seem to be some other Gets and Finds that could return a component or a component on a gameObject. As you can see above, the use of GameObject.Find and .GetComponent:

ponteControl = GameObject.Find("Ponte_Previz1");
var ponteCheck = ponteControl.GetComponent(Anim_Ponte);

Is there a good/better/best (¿completely different?) method?

There is no ‘best’ method, there are methods that fit a particular set of circumstances.

For example, dragging to an exposed variable works in some situations but not all. You can’t always establish the relationship ahead of time.

Let’s look at another example you gave…

 levelStatus = FindObjectOfType(LevelStatus);

That will work great in some situations like with a singleton state machine manager. However what happens if you need multiple objects running that same script?

ponteControl = GameObject.Find("Ponte_Previz1"); 
var ponteCheck = ponteControl.GetComponent(Anim_Ponte);

This is the version I find myself using more often than not. But I wouldn’t call it the ‘best’ way. Unity gives you enough flexibility that some situations might have multiple script access methods that fit the bill. At that points it’s personal taste and performance considerations.

I’ve also used static singletons, it fits some requirements quite well. But most situations it doesn’t.

Lastly:

If you could take a look at this thread:

http://forum.unity3d.com/viewtopic.php?p=123395#123395

and let me know if you had any tho’ts? I am having a spot of bother with the caching on one of my scripts.

I know I’m hopeless, but I’ll keep trying the frontal assaults. That’s what riflemen are for when they [edit] The Enemy [/edit] have entrenched machine guns… If you keep trying, you might just get thru… mebbe…

What is the practical difference between:

someComponent = GetComponent(SomeComponent);

and

someObject = GameObject.Find("SomeObject");
someComponent = someObject.GetComponent(SomeComponent);

[edited for clarity]

someComponent = GetComponent(SomeComponent);

This by itself implies that you’re looking for a component of the same GameObject the script is attached to.

Think of it conceptually as a different expression of…

someComponent = gameObject.GetComponent(SomeComponent);

In the following on you’re explicitly looking for a component of someObject.

someObject = GameObject.Find("SomeObject");
someComponent = someObject.GetComponent(SomeComponent);

So there is no practical difference, that is if someObject is the same GameObject your script is running on.

As an addendum, I should explain a bit as to why it works as it might help.

All scripts have a base class of MonoBehaviour. If you look at the above documentation and scroll down you will see that GetComponent is an inherited function. The chain of inheritance goes all the way back to the Component class.

So when you omit the object, it’s essentially going to assume you mean ‘the current object’, which can be also be expressed in the script as gameObject.

You can use the same knowledge to do away with calling GetComponent altogether in a number of cases. If you look in the same documentation for the inherited members you take advantage of that all the time.

For example you might use the following piece of code in a script.

audio.Play();

Notice you didn’t have to explicitly call GetComponent() to find the audio source.

So -

Just being pedantic…

If you only use GetComponent, you are only looking on the current came object, which is why (by coincidence?) my using FindObjectOfType was working, as it looks at all objects in the game (and I presume) returns the first one of that type it finds?

Are there any practical reasons to change from FindObjectOfType, to the FindObject/GetComponent(in that object) method? (other than my phantom null in the other thread) using FindObjectOfType is working, but I don’t really know why, as I’ve kit bashed it from other places.

[additionally]

Riiiiight.

And this only worked:

// Check player damage
	if (playerStatus.Health < 0  !playerStatus.dead) {
		playerStatus = GetComponent(PlayerStatus);
		playerStatus.OnDeath();
	 }

because it was attached to the same gameObject.

In the end this code should be redundant, as I’d taken to caching the playerStatus link on Start().

I was thinking I’d used GetComponent without a gameObject.Find and it had worked. Now I’m realizing that they were both attached next to each other.

Well THAT code is going away!

You mention “Find/Get in that object”. Just to clarify, as shown in the post above. If the script you want to find is attached to the same GameObject, you can do away with FindObject() altogether and just use gameObject.GetComponent or GetComponent. You would only need FindObject if it is attached to a -different- game object.

Are there are multiple copies of whatever class you’re trying to get a link to with FindObjectOfType. If there are more than one than it’s pot luck which one you’ll get.

Also keep in mind, speed. FindObject is slow and it’s not good to have it in your Update() or other often called function.

Yeah that code bit makes me scratch my head.

See, you learn something new every day with Unity. I know I do! For example Neil showed me this morning on irc you can also use GetComponent with a script link itself.

remoteScript.GetComponent()

is equivalent to

remoteScript.gameObject.GetComponent()

No need to have a link to the remote game object if you already have a link to the script. For if you have a link to a component, you have a link to the game object the component is attached to.

See that handy gameObject at the bottom of the variable list!