Get the FULL version

Using static variables in Unity3D

Using static variables in Unity3D thumbnail

This post explains how to use static variables when programming scripts for the Unity3D engine. The example scripts in this post are written in C#, but the same guidelines apply for JavaScript.

Before delving deeper into the subject, it goes without saying that static variables should be avoided at all costs, for a great number of reasons that can be easily be found on the internet. It’s better to use a Singleton creational pattern in most cases. with that in mind, here’s a short definition of static variables: they are variables that belong to a class, and not the objects the class creates. This means that static variables retain the same value, regardless of the object from a given class. Another characteristic is that, as long as the class is in the memory, they are still valid references. Static variables are initialized by the compiler right before the class creation, and before any other variables or methods. But what does it mean for Unity3D scripts?

It means that one doesn’t need to create a class object to read or modify a variable’s value. As a result, it is only required to get references to game objects and components one single time. Here’s an example: imagine 50 enemies on a single Unity3D scene and all these enemies have an A.I. script attached that requires the the player’s Transform to work correctly, so, the Awake() method of each enemy, without using of static variables would be:

public class EnemyBehaviour: MonoBehaviour 
{
	private Transform playerTransform;
	
	void Awake()
	{
		playerTransform = GameObject.FindWithTag("Player").GetComponent<Transform>();
	}

	void Update()
	{
		//do something based on the player's position
		if(playerTransform.postion.x>100)
		{
			//Do something
		}		
	}
}

To do the same thing only once by using a static variable, a script named GameController is created. It gets the player’s Transform just one time and stores it into a static variable:

public class GameController : MonoBehaviour 
{
	//creating a static variable
	public static Transform playerTransform;
	
	void Awake()
	{
		playerTransform = GameObject.FindWithTag("Player").GetComponent<Transform>();
	}
}

And then, whenever the enemy A.I. script needs to know about the player’s character position, just call the said variable:

public class EnemyBehaviour: MonoBehaviour 
{
	void Update()
	{
		//acessing the static variable
		if(GameController.playerTransform.position.x > 100)
		{
			//Do something
		}		
	}
}

Notice that in the second example, we needed one Awake() method call to get a reference to the player’s game object Transform, whereas in the first one, we would be calling one Awake() method for each enemy, thus calling the Awake() method 50 times.

In the last example, a static variable was used, and even with 50 enemies in the scene, it would still require a single Awake() method call. That’s because another script (GameController) was used to get a reference to the player’s Transform, and this reference was exposed by the static variable. The Awake() method was not even necessary.

When should static variables be used in Unity3D?

With that last example in mind, it is recommended to use static variables when storing references to game objects and components that are often repeated in multiple scripts, inside their Awake() and/or Start() methods. And not only for that; primitive type variables that are relevant to the game’s rules are also good candidates for static variables, such as: the game’s score, player’s health, game’s state (playing, paused, game over), the player’s state (respawning, alive, dead), to name a few.

When should they be avoided

Now that you know when to use them, these are the cases when static variables shouldn’t be used in Unity3D: everywhere else. Unless there is no other way around or if you are implementing the Singleton Design pattern, avoid the use of static variables at all costs.

As a rule of thumb, don’t create static variables unless it’s clear that it will help improve performance. It is always easier to replace all object references in various scripts with a static variable than the other way around, which would involve messing with already created classes leading to unnecessary code refactoring. When it comes to static variables in Unity3D, less is definitively more.

Always reset the values of static variables at the beginning of the script

Another reason to use a small number of static variables, is that they always need to be reset. I will exemplify: imagine a static boolean variable named isDead to track whether the player’s character has died or not. It’s set to false by default, and let’s assume that when it is true, the game loads the game over screen, which is in another scene:

public class GameController : MonoBehaviour 
{
	/*creates a static variable to check if 
	the main character has died*/
	public static bool isDead = false;
	
	void Update () 
	{
		//if the main character is dead
		if(isDead)
		{
			//Loads the 'Game Over' scene
			Application.LoadLevel("GameOver");
		}
	}
}

The above script will work just fine, and after the main character’s death, Unity3D will load the ‘GameOver’ scene. Although, upon returning to the game’s scene to play it again, Unity3D will instantly change to the ‘Game Over’ scene. What will happen is that static variables are class variables, and they persist as long as the class is in the memory, meaning that line 5 will be executed only once, per game execution. As for the above example, it means that isDead is going to be always true. This behavior will continue to occur if the isDead value is not reset at the beginning of the script.

To avoid that from happening, static variable values must be assigned inside the Awake() or Start() methods. Rewriting the above example, the static variable could be reset by assigning a value to it in the Awake() method:

public class GameController : MonoBehaviour 
{
	/*creates a static variable to check if 
	the main character has died*/
	public static bool isDead = false;
	
	void Awake()
	{
		//resetting isDead value to 'false' 
		isDead = false;
	}
	
	void Update () 
	{
		//if the main character is dead
		if(isDead)
		{
			//Loads the game over scene
			Application.LoadLevel("GameOver");
		}
	}
}

This will make the variable work as expected. Always remember to reset static values at the beginning of the scripts! Not doing that could lead to disastrous consequences.

3 Comments to “Using static variables in Unity3D”

  1. GFX47 says:

    I think there’s an error in the first code example, line 13:

    should be

    if(playerTransform.postion.x>100)

    instead of

    if(GameController.playerTransform.postion.x>100)

Leave a Comment

Post Comments RSS