Go to Top

Script Interaction – GetComponent in UnityScript

In this tutorial

  • Accessing another script from inside the object
  • How does GetComponent work?
  • Getting many components
  • Interaction between objects.
  • Interaction between objects within the hierarchy

You can find the exact same tutorial using C# here or using Boo here .

Introduction

One recurrent issue when starting with Unity is how to access the members in one script from another script. Many would think that dereferencing from the script name would be enough, they quickly realize it is not.

When developing a program, variables are stored in the memory at different locations. If an object could see any other object members, there would a risk to modify them even though it was not intended. If for instances two objects hold the same script with the same variable names, the compiler would not be able to figure out which one we are referring to.

To prevent this issue, each object in memory cannot see other objects. It is then necessary to tell one object where the variable it needs is in memory. The whole pointer principle has been dropped long ago and now we are using reference instead (which actually uses pointer internally).

There are actually various way to access variables, some are better than others and some are simply to be used in particular situations.

To summarize, there are three ways:

-GetComponent, the most common, also the one that confuses most at first

-SendMessage, it might look easier to grasp but it is also less efficient.

-static variable, the easiest to use but also the most complicated to fully understand at first.

In this tutorial we will cover the GetComponent section using UnityScript.

Create a new scene and add an empty game object and name it “ObjectA”. Create two scripts named “ScriptA” and “ScriptB”. Add both scripts to ObjectA.

Open up both scripts in the editor and add these lines:

ScriptA.js

var variableBInA:int;
var otherBInA:int;
function Start()
{
}
function Update()
{
      if (Input.GetKeyDown(KeyCode.Space))
      {
            variableBInA = ScriptB.GetVarB();
	    otherBInA = ScriptB.variableB;
	    if (variableBInA > 0)
		ScriptB.AddVarB(10)
       }
}

ScriptB.js

private var variableB:int;

function Start()
{
	variableB = 20;
}

function Update()
{
	if (Input.GetKeyDown(KeyCode.P))
		print(variableB);
}

function GetVarB()
{
	return variableB;
}

function AddVarB(num:int)
{
	variableB += num;
}

Trying this code will simply return error “An object reference is required to access non-static members”.

We need to tell ScriptA where is ScriptB so that it can access its members. Since our scripts are both on the same object we simply need to declare a variable of type of the script and use GetComponent to find the script.

Accessing another script inside the object

Modify ScriptA with:

var scriptB:ScriptB;
var variableBInA:int;
var otherBInA:int;

function Start()
{
	scriptB = GetComponent(ScriptB);
}

function Update()
{
	if (Input.GetKeyDown(KeyCode.Space))
	{
		variableBInA = scriptB.GetVarB();
		otherBInA = scriptB.varB;
		if (variableBInA > 0)
		{
			scriptB.AddVarB(10);
				print("In ScriptA otherBInA is " + otherBInA);
                }
	}
}

With the modifications, run the game, press P, it should show 20 in the console, press Space and then P again, the value is now 30. It was also possible to access varB and assign it directly to varBInA since varB is public.Note that accessing methods  is done the same as for variables.

If the members were private, it would not be possible to access them.

How does GetComponent works?

First we declare an object of the type of the script we want to reach.

ScriptB script;

The GetComponent function will look inside the object to find a component corresponding to the type we passed. If none is found a null reference is returned and our script variable will not do anything. If a component of type ScriptB is found then the address of that component is passed to the variable script, the variable now points to the ScriptB component stored somewhere in memory. In order to access the public members of ScriptB, we just need to dereference the script variable using the dot operator.

script.PublicMembers;

Private members will remain inaccessible.

You might see the command as such : GetComponent("ScriptName"), the  quotation marks will work but will also throw a warning. Avoid this use and keep it simple.

Reference

So I can cache component with GetComponent?

Yes, and it is recommended to do so for some regularly used component like the Transform.

Cache with a few simple lines of code like:

var trans:Transform;

function Start(){
     trans = GetComponent(Transform);
}

function Update(){
     trans.position.x +=10;
}

This will save some computation.

Getting many components

What if our ObjectA has many ScriptB within itself. Duplicate the ScriptB twice so ObjectA has three of them.

ScriptA becomes:

private var script:ScriptB[];

function Start()
{
	script = GetComponents(ScriptB);
}
function Update()
{
	if (Input.GetKeyDown(KeyCode.Space))
	{
		for (var i : int = 0; i<script.Length; i++)
			script[i].AddVarB(i);
	}
}

Notice the plural of GetComponents, this is the key. Run the game, press P, the console prints out three 20. Press Space and P again, the console should look like this:

Console

Because I used the value of i in the loop as parameter of the function, each script has received a different value. Note that since the loop starts from 0, one script does not change.

Interaction between objects.

We can also get two objects to interact in a similar way. Create a new object named “ObjectB”. Remove the ScriptB component from ObjectA and add it to ObjectB.

Run the game, you can print but pressing Space will throw a Null reference exception. This is due to the fact that the ScriptB is no more on ObjectA so GetComponent simply does not find it. We need to find the ObjectB first using GameObject.Find(“ObjectB”).

You only need to add the line below in the ScriptA:

function Start () 
{
     script =GameObject.Find ("ObjectB").GetComponent(ScriptB);
}

GameObject.Find() first finds the object passed as parameter and then looks for the required component inside of it. It is recommended to perform those actions in the Start or at a time of the game where lags will not affect the gameplay. GameObject.Find and GetComponent are expensive functions since they need to iterate through the whole Hierarchy. If your scene only includes 10 objects, it will be fine but if it holds thousands of them you will surely see a bad effect. Consider calling these in the Start function.

Interaction between objects within the hierarchy

Drag ObjectB into ObjectA.

Run the game and you will notice it works fine. Still, we can make it happen better by using commands that tell the compiler that ObjectB is a child of ObjectA. Hence, no need search all the objects of the scene.

var script :ScriptB;
function Start () {
    script =transform.Find ("ObjectB").GetComponent(ScriptB);
}

GameObject is swapped for transform. Indeed, a child object belongs to the transform of the parent so we need to look into the transform to find our object.

Even better, we can use:

function Start () {
     script =GetComponentInChildren(ScriptB);
}

Note that it also works if you have children of children holding the script. Create an “ObjectC”, add ScriptB to it and add the object to ObjectB. Now A has B which has C.

Change ScriptB for:

function Update(){
    if(Input.GetKeyDown (KeyCode.P))print (gameObject.name+" "+varB);
}

Run the game, you will see that both scripts are found and altered.

GetComponentsInChildren will work the same if all children have many instances of one script.

Interaction in action

In order to give a visual and practical representation, the video below summarizes some of the uses for GetComponent. Although it is in C#, the principle remains the same in UnityScript.

, ,

One Response to "Script Interaction – GetComponent in UnityScript"

  • karthik ts
    March 29, 2013 - 10:22 pm Reply

    Great explanation….
    thanks a lot…

Leave a Reply

%d bloggers like this: