GameObject.FindGameObjectWithTag

Hi I was wondering what the difference was between two lines of code. In the first script it says theBall = GameObject.FindGameObjectWithTag("Ball").transform; but in the second script it says if(!GameObject.FindGameObjectWithTag("Music")) etc… So what is the difference? Why do I have to put transform at the end of one line of code and not the other. Also isn’t the variable in function Start() supposed to be out of scope since it is inside a function?

static var playerScore01 : int = 0;		
static var playerScore02 : int = 0;

var GuiSkin1 : GUISkin;
var theBall : Transform;

function Start () 
{
	theBall = GameObject.FindGameObjectWithTag("Ball").transform; 
	
}

static function Score (wallName : String) 				
{
	if(wallName == "rightWall")
	{
		playerScore01 += 1;
	}
	else
	{
		playerScore02 += 1;
	}
	
}

function OnGUI () 
{	
	GUI.skin = GuiSkin1;
						              
	GUI.Label (new Rect (Screen.width/2 - 150 - 18, 20, 100, 100),"" + playerScore01);	
	GUI.Label (new Rect (Screen.width/2 + 150 - 18, 20, 100, 100),"" + playerScore02); 
	
	if (GUI.Button ( new Rect (Screen.width/2-121/2, 35, 121, 53), "RESET"))	//Screen.Width/2-121/2 because anchor point starts at top left corner...
	{
		playerScore01 = 0;
		playerScore02 = 0;
		
		theBall.gameObject.SendMessage ("ResetBall");
		
	}

}

&&

var musicPrefab : Transform; 
function Start () 
{
	currentScore = 0;
	
	if(!GameObject.FindGameObjectWithTag("Music"))
	{	
		var mManager = Instantiate (musicPrefab, transform.position, Quaternion.identity)
		mManager.name = musicPrefab.name; 
		DontDestroyOnLoad (mManager); 
	}
}

The variable theBall is of type Transform. So when you are using

theBall = GameObject.FindGameObjectWithTag("Ball").transform;

you are finding the game object Ball and storing its transform into theBall variable.

If theBall variable was of type GameObject then you could have written

var theBall: GameObject;
theBall = GameObject.FindGameObjectWithTag("Ball");

And in second case where you are writing

if(!GameObject.FindGameObjectWithTag("Music"))

you are checking for if the game object tagged Music is present or not and not checking for the transform of the Music game object that’s why transform is not used in the second case.

Just so you know when you are assigning the value to you musicPrefab variable which is of type Transform you will write

musicPrefab = GameObject.FindGameObjectWithTag("Music").transform;

So that you will store the value of transform of Music game object in musicPrefab.

As to your question there is no need to use the Transform in the first set of code.

Try changing line 5 to

var theBall : GameObject;

And line 9 to

theBall = GameObject.FindGameObjectWithTag("Ball");

This should produce identical results.

Some thoughts on Transform versus GameObject:

Transform is a component on the GameObject. The unique thing about a Transforms is that every GameObject must have one and only one.

Some of unity’s methods will implicitly convert a GameObject into a Transform, or vice versa. Check out the scripting reference for details. You can always explicitly convert between the two as follows.

// To get the GameObject
transform.gameObject;
//To get the Transform
gameObject.transform;

The main reason you might want to grab a transform instead of a GameObject is if you want to affect position directly.

The main reason you might want to grab a GameObject instead of a Transform is if you want to affect other components on the GameObject

Edit:
theBall is not out of scope because it is declared on line 5

Well, both scripts appear to do something completely different to one another.

The first script will find a GameObject tagged ‘Ball’, and reference it as a Transform in a variable called ‘theBall’.

The second script will find a GameObject tagged ‘Music’, and not reference it at all.

The GameObject is the actual object you see in the game scene, this is the GameObject - the physical being of the object. Attached to GameObjects are other components, such as the Renderer (how it looks), maybe a Rigidbody (how it collides), and a Transform (its position/rotation/scale).

You can reference it as a GameObject if you want:

var theBall : GameObject;

But if you only want to talk to the transform of it (maybe change the scale), then you will need to tell unity that - by added ‘.transform’ at the end:

theBall.transform.localScale.x = 2;

Notice how I added the ‘.transform’? Thats because I’m referring to the Transform of the GameObject only. If I had the variable as a Transform, then I don’t need to refer to it again:

var theBall : Transform;
theBall.localScale.x = 2;

Notice how I don’t need the ‘.transform’ anymore? Thats because I’m already referring to the Transform, because I’ve declared the variable as a Transform type.

Now - In terms of having a variable inside, or outside a function - that depends on what your doing with it. Odds are, you’ll need it outside the function. Example:

function Start(){
	
	var Player = GameObject.FindGameObjectWithTag('player');
}

function Update(){
	
	Player.transform.localScale.x = 2;
}

This will throw an error, because the Update function is trying to find a variable called ‘Player’, which does not exist - it only exists within the Start function - see it as a type of ‘localised’ variable only ‘visible’ to that function - in this case, the Start function.

If you’ll have a load of functions using this variable, then yes, you do want to put it outside:

var Player : Transform;

function Start(){
	
    Player = GameObject.FindGameObjectWithTag('player').transform;
}

function Update(){
	
	Player.localScale.x = 2;
}

function KillPlayer(){
	
	Destroy(Player.gameObject);
}

A few things to notice here, I now have the variable outside, so now all functions can ‘see’ it, and use it. I’ve defined the variable as a Transform, so in the Start function, I need to add ‘.transform’ at the end as the ‘GameObject.FindGameObjectWithTag’ returns the GameObject, the my variable is expecting it’s Transform.

Also, the Update function: I don’t need to include the ‘.transform’ as it already knows its a Transform. Although, in the KillPlayer function, I have ‘Player.gameObject’.

The Destroy method expects a GameObject, so I need to add ‘.gameObject’ at the end because Player alone is a Transform, remember?

Hope this clears things up:

  • Item.gameObject - return the GameObject
  • Item.transform - return the Transform
  • Item.gameObject.transform - return the Transform
  • Item.gameObject.transform.gameObject - return the GameObject
  • Item.transform.gameObject - return the GameObject

You can even have something like this:

Item.gameObject.transform.gameObject.transform.gameObject.transform.gameObject, which will return the gameObject - but this is ridiculous.