multiple javascript files sharing variables

Hello I am working on a game right now that has a timer count down until it reaches zero. The code that controls the timer is in one script and i have another javascript file that makes the rest of the game run. In this file it is able to detect if the task was completed and the player won.

I want the timer to stop if the player won. Is there some form of inheritance with javascript so that i can use the playerHasWon variable to stop the clock?

i could just reuse the code in the clockscript but i would prefer to do it through inheritance. If inheritance is possible with javascript. I am new to the language but understand programming constructs.

Edit: i guess all i really need to the playerHasWon variable to be accessible through all the javascript files like a global variable

UnityScript supports inheritance, but it doesn’t sound like that’s what you need here. Given what you describe, I think the most straightforward solution might be to link the components together using references so that they can interact directly.

For info on linking game objects and components in this way, see here.

make the variable as static

static var foo

outside the update loop should do the trick… to use the variable inside another script, you type:

if (nameofscript.foo == bar) {
#%^^#%
};

also, check out

GameObject.BroadcastMessage

i dont think i was being clear with my problem so i will try again.

I have two differnt javascript files

  1. controls the game and decides whether or not the player has won
  2. controls the countdown timer that shows how much longer the player has left

i have the variable playerHasWon in file number 1 and i need access to that variable in file number 2 so that i can stop the timer once player has won.

so how would i access the playerHasWon variable in file 2?

That was how I understood the problem initially, and the information on accessing other game objects is relevant, I think.

Any game object can access any other game object via a variety of means, some (or perhaps all) of which are detailed in the link I provided. Once you have access to a game object, you can then acquire a reference to any component of that object using GetComponent(). In this way, for all practical purposes any component in the scene can interact directly with any other component in the scene. In your case, for example, the ‘game controller’ component and the ‘countdown timer’ component can interact with one another so as to stop the timer when the level is complete.

As for accessing specific fields of a script/class, you can make those fields public, or you can provide accessors or public functions that implement specific behaviors.

To summarize, there are three steps involved here, more or less:

  1. Get a reference to the game object of interest.
  2. Get a reference to the component of interest.
  3. Interact with the component via its public interface.

There are ways to bypass step 1 as well (for example, you can assign a reference to the component directly, or search for the component by type, although that may be less efficient than other options, depending).

If that still doesn’t answer the question, perhaps you could clarify which of the steps described above you’re unsure of.

582113--20722--$Picture 1.png

Ok i am getting closer to understanding how to do this, keep in mind i am new to javascript so i might ask some pretty stupid questions.

the code above is from Unitys example of accessing other game objects. What I think i am understanding is that after the code is executed otherScript is now a reference to OtherScript.js and
otherScript.DoSomething() is calling the DoSomething function of the OtherScript.js file

and since i need access to the variable playerHasWon i would replace otherScript.DoSomething() with

otherScript.playerHasWon

let me know if im correct, thanks for the help

They’re not stupid questions :slight_smile:

Yes, that’s accurate. (Technically otherScript is a reference to an instance of the class defined in OtherScript.js, but yes, you’ve got the right idea.)

ok well i think might have a problem then, since in the OtherScript.js it has an instance of a Card class. The card class has two instance variables and playerHasWon is not one of them, it is just a global variable accessible by all the functions on that javascript file. Is my way around that to just add the variable playerHasWon to be an instance variable in the Card class so that i can access it?

I’m not sure I follow completely; you might just go ahead and post your OtherScript.js file so we can take a look at it.

(It sounds to me though like ‘playerHasWon’ is just a member variable, in which case you should be able to access it as ‘otherScript.playerHasWon’, provided the variable is public.)

gameScript( i bolded all the times i mention the variable playerHasWon)

		var cols:int =4;
		var rows:int =4;
		var totalCards:int = 16;
		var matchesNeededToWin:int = totalCards * 0.5;
		var matchesMade:int = 0;
		var cardWidth:int = 100;
		var cardHeigth:int = 100;
		var aCards:Array;
		var aGrid:Array;
		var aCardsFlipped:ArrayList; // will store two cards the player flipped over
		var playerCanClick:boolean;
		[B]var playerHasWon:boolean = false;[/B]

function Start()
{
	playerCanClick = true;
	aCards = new Array();
	aGrid = new Array();
	aCardsFlipped = new ArrayList();
	
	BuildDeck();
	
	for(i=0; i<rows; i++)
		{
			aGrid[i] = new Array();
		
		for(j=0; j<cols; j++)
			{
				var someNum:int = Random.Range(0,aCards.length);
				aGrid[i][j] = aCards[someNum];
				aCards.RemoveAt(someNum);
			}
		}	
}
function OnGUI () 
{
	GUILayout.BeginArea (Rect (0,0, Screen.width,Screen.height));
	BuildGrid();
	[B]if(playerHasWon) BuildWinPrompt();[/B]
	GUILayout.EndArea();
	print("building grid");	
}

class Card extends System.Object
{
		var isFaceUp:boolean = false;
		var isMatched:boolean = false;
		var img:String;
		var id:int;
	


	function Card(img:String, id:int)
	{
		this.img = img;
		this.id = id;
	}

}	
	function BuildGrid()
	{
		GUILayout.BeginVertical();
		GUILayout.FlexibleSpace();
		for(i=0; i<rows; i++)
		{
			GUILayout.BeginHorizontal();
			GUILayout.FlexibleSpace();

			for(j=0; j<cols; j++)
			{
				var card:Object = aGrid[i][j];
				var img:String;
				
			if(card.isMatched)
			{
				img= "blank";
			}
			else
			{	
				if(card.isFaceUp)
				{
					img = card.img;
				}
				else
				{
					img = "wrench";
				}
			}	
			GUI.enabled = !card.isMatched;
				if(GUILayout.Button(Resources.Load(img), GUILayout.Width(cardWidth)))
				{
					if(playerCanClick)
					{
						FlipCardFaceUp(card);
					}
					Debug.Log(card.img);
					GUI.enabled = true;				
				}
						
			}
			GUILayout.FlexibleSpace();
			GUILayout.EndHorizontal();
		}
		GUILayout.FlexibleSpace();
		GUILayout.EndVertical();
	}
	
	function BuildDeck()
	{
		var totalRobots:int = 4;
		var card:Object;
		var id:int = 0;
		
		for(i=0; i<totalRobots; i++)
		{
			var aRobotParts:Array = ["Head", "Arm", "Leg"];	
			for(j=0; j<2; j++)
			{
				var someNum:int = Random.Range(0, aRobotParts.length);
				var theMissingPart:String = aRobotParts[someNum];
				aRobotParts.RemoveAt(someNum);
				
				card = new Card("robot" + (i+1) + "Missing" + theMissingPart, id);
				aCards.Add(card);
				
				card = new Card("robot" +(i+1) + theMissingPart, id);
				aCards.Add(card);	
				id++;
			}
		}
		
	}

	function FlipCardFaceUp(card:Card)
	{
		card.isFaceUp=true;
		if(aCardsFlipped.IndexOf(card) <0)
		{
		aCardsFlipped.Add(card);	
		
		if(aCardsFlipped.Count == 2)
		{
			playerCanClick = false;
			yield WaitForSeconds(1);
			
			if(aCardsFlipped[0].id==aCardsFlipped[1].id)
			{
				//Match occurs
				aCardsFlipped[0].isMatched=true;
				aCardsFlipped[1].isMatched=true;
				matchesMade++;
				if(matchesMade>=matchesNeededToWin)
				{
					[B]playerHasWon=true;[/B]
				}
				
			}
			else
			{
			aCardsFlipped[0].isFaceUp=false;
			aCardsFlipped[1].isFaceUp=false;
			}
			aCardsFlipped = new ArrayList();
			
			playerCanClick= true;

		}
		}
		
	}

	function BuildWinPrompt()
	{
		var winPromptW:int = 100;
		var winPromptH:int = 90;
		var halfScreenW:float = Screen.width/2;
		var halfScreenH:float = Screen.height/2;
		var halfPromptW:int = winPromptW/2;
		var halfPromptH:int = winPromptH/2;
		
		GUI.BeginGroup(Rect(halfScreenW-halfPromptW, halfScreenH-halfPromptH, winPromptW,winPromptH));
		GUI.Box (Rect (0,0,winPromptW,winPromptH), "You beat Will's game!");
		if(GUI.Button(Rect(10,40,80,20), "Play Again?"))
		{
			Start();
			Application.LoadLevel("title");
		}
		GUI.EndGroup();	
	}

my attempt at getting the playerHasWon variable in the clockScript

function Update()
{
	otherScript = GetComponent(gameScript);
	playerWon = otherScript.playerHasWon;
	if(!isPaused)
	{
		DoCountdown();
		
	}
	
	
}

function DoCountdown()
{
	
	timeRemaining = startTime - Time.timeSinceLevelLoad;
	percent = timeRemaining/startTime *100;
	if(timeRemaining<0  playerWon)
		{
			timeRemaining=0;
			isPaused=true;
			TimeIsUp();
		}

Just a couple of questions to help clarify things:

  1. Is the first script you posted named ‘gameScript.js’, and the second named ‘clockScript.js’?

  2. Are the two scripts attached to the same game object?

  3. What’s going wrong exactly? Are you getting a compiler error? A run-time error? (If you’re getting an error message of some sort, post it here.)

Also, if that’s not the entirety of clockScript.js (which I assume it’s not), I’d post that script in its entirety as well.

  1. yes
  2. no the 1st is attached to the cards in the game the second is attached to the countdown timer
  3. the error i am getting is NullReferenceException: Object reference not set to an instance of an object

entirety of the clock script

 var isPaused : boolean = false;
var startTime : float; //in seconds
var timeRemaining: float; //in secs
var percent: float;
var clockFG:Texture2D;
var clockBG:Texture2D;
var clockFGMaxWidth:float; // the starting width of the foreground bar
var playerWon:boolean;

function Start ()
{
	guiText.material.color = Color.black;
	startTime = 190.0;
	clockFGMaxWidth = clockFG.width;
}

function Update()
{
	otherScript = GetComponent(gameScript);
	playerWon = otherScript.playerHasWon;
	if(!isPaused)
	{
		DoCountdown();
		
	}
	
	
}

function DoCountdown()
{
	
	timeRemaining = startTime - Time.timeSinceLevelLoad;
	percent = timeRemaining/startTime *100;
	if(timeRemaining<0  playerWon)
		{
			timeRemaining=0;
			isPaused=true;
			TimeIsUp();
		}
	else
	{
			
		ShowTime();	
		Debug.Log("Time left is" + timeRemaining);	
	}
	
	
}

function PauseClock()
{
	isPaused=true;
}

function UnpauseClock()
{
	isPaused=false;
}

function ShowTime()
{
	var minutes : int;
	var seconds : int;
	var timeStr : String;
	minutes = timeRemaining / 60;
	seconds = timeRemaining % 60;
	timeStr = minutes.ToString() + ":" + seconds.ToString("D2");
	guiText.text = timeStr;
}
function TimeIsUp()
{
	Debug.Log("Time is Up!!!!");
	
}

function OnGUI()
{
	var newBarWidth:float = (percent/100) * clockFGMaxWidth; // width of the foreground bar
	var gap:int = 20; //spacing variable
	GUI.BeginGroup (new Rect (Screen.width- clockBG.width - gap, gap, clockBG.width, clockBG.height));
	GUI.DrawTexture(Rect(0,0,clockBG.width, clockBG.height), clockBG);
	GUI.BeginGroup(new Rect(5,6,newBarWidth, clockFG.height));
	GUI.DrawTexture(Rect(0,0,clockFG.width,clockFG.height),clockFG);
	GUI.EndGroup();
	GUI.EndGroup();
	
	if(timeRemaining == 0)
	{
		YouLost();
	}
	
}

function YouLost()
{
		var winPromptW:int = 100;
		var winPromptH:int = 90;
		var halfScreenW:float = Screen.width/2;
		var halfScreenH:float = Screen.height/2;
		var halfPromptW:int = winPromptW/2;
		var halfPromptH:int = winPromptH/2;
		
		GUI.BeginGroup(Rect(halfScreenW-halfPromptW, halfScreenH-halfPromptH, winPromptW,winPromptH));
		GUI.Box (Rect (0,0,winPromptW,winPromptH), "You Lost!!! :(");
		if(GUI.Button(Rect(10,40,80,20), "Play Again?"))
		{
			Application.LoadLevel(1);
		}
		GUI.EndGroup();		
	
}

ughh i wish you could program unity in java, cause then i would know exactly how to fix this haha

For what it’s worth, C# is more similar to Java than is UnityScript, so it might be that you’d find C# to be more immediately intuitive.

However, I think the problem here is language-independent, more or less, and would be the same regardless of what language you were using.

The problem is likely with this line:

otherScript = GetComponent(gameScript);

Without additional qualification, GetComponent() searches for the specified component in the same game object to which the script containing the GetComponent() call is attached. If the game object to which the clockScript component is attached doesn’t have a gameScript component attached, then you’ll get a null reference exception when you try to deference ‘otherScript’.

If the scripts are in fact attached to different game objects, then you’ll need to get the two objects communicating in one way or another; this is where the link on ‘accessing other game objects’ that I posted earlier comes into play.

Alright thanks it worked like a champ! all i did was link the gameScript.js to the clock object then change one small piece to the code and i am good to go.

however, if i were using java wouldnt all i have to do is extend the clockScript class from gameScript and the i would get the gameScripts variables through mutator methods.

The reason i am using javascript currently is because i bought a book on Unity and the language it uses is javascript, but once i am done with the book i will try and switch over to c#

thanks again for all the help!!

Although the details differ somewhat, inheritance is supported in all of the languages in question (Java, UnityScript/JavaScript, C#, and presumably Boo as well, although I haven’t used Boo myself).

So, you could do what you describe in UnityScript. However, the cases where you’d want to use inheritance when working in Unity are fairly rare, I think (although not nonexistent). Usually, you’d just use multiple components/scripts instead. And even outside of Unity, it’s usually recommended to favor composition over inheritance, and only to use inheritance where there’s a clear ‘is a’ relationship.

No problem :slight_smile:

ok, well there still is a lot i have to learn then haha, i just took java in ap computer science as a jr in HS so that is the language i am most familiar with now, and just hope to learn more and more languages