How to get a variable from another script in Unity

How to get a variable from another script in Unity (the right way)

In Scripting Basics by John FrenchUpdated 42 Comments

Getting a variable from another script in Unity can be pretty straightforward.

In fact, even if you’re only just getting started with Unity, chances are you’ve already created a public reference between a script variable and another object, by dragging and dropping it in the Inspector.

You might have already accessed components on a game object from code, or created connections between objects through an interaction between them, such as when two objects collide.

But what if you want to create a connection between different scripts or components, on different objects, that don’t otherwise interact?

How can you keep track of game-wide, global variables, like a score or the player’s health?

And what’s the best way to do that, without making a mess of your project?

In this article, you’ll learn the basic methods for accessing a variable on another script. along with some best practice tips to help you keep your project clean and easy to manage.

What you’ll find on this page:

Let’s get started…

Overview video

For a general overview of how to get a variable from another script, try my video, or continue to the full article below.

How to access a variable from another script in Unity

The most straightforward way to access information that’s in another script is with a reference to the type of script or component that you want to access.

For example, imagine that I’m writing a Player Health script that contains a Player Hurt function.

Whenever the player is hurt, and the function is triggered, it takes some health off of the player.

public class PlayerHealth : MonoBehaviour 
{ 
    float hp = 100;

    public void PlayerHurt()
    {
        hp -= 20;
    }
}

Simple enough, but what if I want to also play a sound effect whenever the player gets hurt?

In this example, the character object has an Audio Source component attached to it.

But how do you connect a script to something else?

Example Unity Scene

In this example, I want to get a reference to an audio source component on my Knight character.

The most straightforward way to communicate with another script, or in this case a component, is to get a reference to it.

A Reference is a type of variable that points to another object in the scene or project.

Reference variables vs Value variables

There are, generally, two types of variables in Unity, References, and Values.

Values are data types, such as numbers, boolean values, Vector 3 values, colours and, strings*, while References are pointers that refer to data that exists elsewhere, such as game objects, components, classes and assets.

The main difference between the two types is how they behave when their data is accessed.

Setting a reference variable creates a link to something else, such as an object, or a script on an object. Many references can exist that all point to the same data and, if the data changes, it changes for all of the references too.

Setting a value type copies whatever data it reads, meaning that the variable and the data it reads can change and they will both be different.

When working in Unity, you’ll be able to tell value types apart from references in the Inspector, where values, such as numbers, can be entered or typed in manually, and references are set by selecting an object, component or asset that exists elsewhere, either in your project or your scene.

If you’re new to Unity, and you’re finding this difficult to visualise, one way to think of it is by imagining a classroom full of people.

A Reference type is the equivalent of writing some information on the board at the front of the room. No one copies it, they just look at it whenever they need to use it, and if it ever changes or is missing (null) then everyone knows because they are all accessing the same information.

A Value type is the equivalent of everyone being told a piece of information once, where each person copies it down individually. If the original information changes, the copies don’t, and everyone’s copy can be different.

* Strings are technically read-only classes, meaning that they are not values, but behave like they are.

In the Player Health script, I’ve created a public Audio Source variable.

Like this:

public class PlayerHealth : MonoBehaviour 
{ 
    public AudioSource playerAudioSource; 
}

Audio sources are components, so their variables are Reference types, meaning that I need to connect the variable I’ve declared with an audio source component in the scene, so that the script knows which audio source I’m referring to.

There are several ways I could do this but the simplest method is to do it manually in the Inspector.

How to set a reference variable using the Inspector

Reference variables will appear in the Inspector as an empty field.

Like this:

Audio Source component reference in the Unity Inspector

References variables appear as an empty field in the Inspector, so long as the variable is either Public or Serialized.

However, this only works if the variable is public or serialized, otherwise, it won’t show up.

Public vs Private variables in Unity

It’s possible to change how a variable can be accessed by setting an Access Modifier.

There are a bunch of different modifiers available but generally speaking, your choice is to make the variable public or private.

Public variables can be accessed by other scripts and, importantly, are visible in the Inspector.

Private variables, however, are not accessible by other scripts and won’t show up in the Inspector.

The access modifier is added as a keyword before the variable type and, if neither is used, the variable will be private by default.

Here’s what it looks like in code:

public float publicFloat; // Public
private string privateFloat; // Private
int privateInteger;  // Private

Even if you’re new to Unity, you may have already used both public and private variables by following tutorials and other examples.

However, if you’re only making a variable public so that you can see it in the Inspector, then you might want to Serialize it instead.

Like this:

[SerializeField] float playerHealth; // Private, but will show in the Inspector

The point of using Serialize Field is to show the variable in the Inspector, but without giving other scripts any access to it. As a rule of thumb, it’s usually better to use serialized variables instead of public ones, as it prevents you from giving scripts access to variables they don’t need.

It’s also possible to make a variable available to other scripts without showing it in the Inspector.

Like this:

// This will not show in the inspector

[HideInInspector] 
public float playerHealth; // Public, but won't show in the Inspector

This can be useful when you do need to keep a variable public, but you don’t need to see it, keeping your Inspector more organised and less cluttered.

It’s generally good practice to keep all of your variables private by default, using Serialize Field if you need to see them in the Inspector.

Then, if another script does need to access it, you can make it public.

However, for the sake of simplicity, in many tutorials and examples, including some on this blog, you will often see a variable marked as public when it only really needs to be serialized.

In this example, the Audio Source reference does not need to be public, as other scripts won’t be accessing it, and the only reason I’m making it public is so that it’s visible in the Inspector.

In which case, I can serialize it instead.

Like this:

public class PlayerHealth : MonoBehaviour 
{ 
    [SerializeField] AudioSource playerAudioSource;
    float hp = 100;

    public void PlayerHurt()
    {
        hp -= 20;
    }
}

Set the public field in the Inspector

Both the script and the audio source are attached to the same game object, which in this case is the player, and connecting the two is as easy as dragging the audio source component to the variable field in the Inspector.

Like this:

Set a reference in Unity in the Inspector

Public reference variables can be set by simply dragging the component to the field.

Alternatively, clicking the Circle Select button, which is to the right of the variable field, will list all of the game objects in the Scene with components on them that match the reference type.

In this case, that’s any game objects with audio source components attached.

Like this: 

Circle Select Unity Inspector

Using circle select lists all of the objects in the scene with components that match the reference type.

Once you have a reference to a component, you’ll be able to get and set its information using the Dot Operator.

The dot operator, a period symbol, allows you to access the member information of a class, such as its public variables.

Like this:

public AudioSource audioSource;

void Start()
{
    // Returns the volume of the audio source
    float volume = playerAudioSource.volume;
}

It also allows you to access publicly available functions on the component, such as the Play Function.

Such as when the player is hurt, for example.

Like this:

public class PlayerHealth : MonoBehaviour
{
    [SerializeField] AudioSource playerAudioSource;
    float hp = 100;
    void PlayerHurt()
    {
        hp -= 20;
        playerAudioSource.Play();
    }
}

But how do you trigger the Player Hurt function in the first place?

Such as when you run into an enemy, for example.

Monobehaviour Scripts, which are scripts that are added to objects are, essentially, components too.

They work in the same way, and can be accessed using reference variables, just like an audio source or any other type of component.

How to create a reference to another script

To create a reference to another script, all you need to do is declare a variable of that type, just like when creating a reference variable to a component or an object.

For example, to create a reference to the Player Health script, simply create a variable of the player health type.

Like this:

public PlayerHealth playerHealth;

Just like with the audio source component, if the reference is public or serialized, you’ll be able to it in the Inspector by dragging an instance of the Player Health script, or an object that has one attached to it, to the empty field.

This will allow you to access the script’s public data using the dot operator, such as the reference to audio source, if it’s public, and through that reference, any public variables or functions it has as well.

For example, it’s possible to trigger the Play Function on the audio source through the script’s public reference.

Like this: 

public class Enemy : MonoBehaviour
{
    public PlayerHealth playerHealth;

    void Start()
    {
        playerHealth.playerAudioSource.Play();
    }
}

However, you wouldn’t normally want to chain scripts together in this way, as it makes the connections between scripts and components easy to break.

Instead, it can be better to provide a limited number of public functions that other scripts are allowed to use and trigger anything else that needs to happen from inside them.

For example, allowing other scripts to change the player’s health directly could be difficult to manage. This is because if you want to change how the health is reduced later on, you’d need to do it on any other scripts that trigger it.

Instead, making the Player Hurt function public allows another script to call it, but not modify any data directly.

Like this:

public class PlayerHealth : MonoBehaviour
{
    [SerializeField] AudioSource playerAudioSource;
    float hp = 100;
    public void PlayerHurt()
    {
        hp -= 20;
        playerAudioSource.Play();
    }
}

Then if something else needs to happen as a result, such as playing an audio source, it can be added in one place.

But what if you want different scripts to inflict different amounts of damage?

Giving the Player Hurt function a float parameter allows you to pass in a variable amount of damage when calling the function.

Like this:

public class PlayerHealth : MonoBehaviour
{
    [SerializeField] AudioSource playerAudioSource;
    float hp = 100;
    public void PlayerHurt(float damage)
    {
        hp -= damage;
        playerAudioSource.Play();
    }
}

Then, to trigger the function from a different script, all you need to do is call it using the reference to the instance of the Player Health component, passing in the amount of damage you want to do.

Like this:

public class Enemy : MonoBehaviour
{
    [SerializeField] PlayerHealth playerHealth;

    void HurtPlayer()
    {
        // Hurts the player
        playerHealth.PlayerHurt(20);
    }
}

However, all of this only works if you already have a reference to the Player Health instance.

Normally, you might drag this to the Enemy script, but what if you can’t drag and drop the object in the Inspector?

For example, what if the enemy is spawned while the game is running?

How can you get a reference to something, without setting it yourself manually in the Inspector?

One option is to use Get Component.

How to use Get Component in Unity

Get Component is a method for finding a specific type of component on an object.

The function searches for a component of a given type and returns it if it finds one.

It can be called on the same object as the script it’s used in or it can be used to find components on other game objects.

So how does it work?

Get Component takes a Generic Type which, in the example below, is entered in place of the T in angled brackets.

GetComponent<T>();

If the angled brackets “<T>” are new to you, don’t worry. Functions that accept generic types simply allow you to specify what type it is that you’re dealing with.

In this case, it’s the type of component or scripts that Get Component should be looking for on the object.

Simply replace T with whatever component type (or class name) that you’re trying to find.

Like this:

GetComponent<AudioSource>();

A common use for Get Component is to set up a script’s references automatically.

For example, if I didn’t want to manually set the audio source component by assigning it in the Inspector, I could set it automatically by using Get Component in the Awake function instead, which is called when the script is first loaded.

Like this:

public class PlayerHealth : MonoBehaviour
{
    AudioSource playerAudioSource;

    void Awake()
    {
        playerAudioSource = GetComponent<AudioSource>();
    }
}

Calling Get Component from within a script searches for the component on the object that the script is attached to.

But, what if you want to search for a script that’s on a child object, or a parent object, or a different object entirely?

How to use Get Component on a different object

Get Component is a function of the Component class and of the Game Object class.

That means that you can call it using a game object reference or with a component reference.

Since all scripts that are attached to objects are components, they inherit the Get Component function automatically, meaning that you don’t need a reference, you can just type it out in a script and it will search on just that object.

Alternatively, if you do have a reference to a different component or a different game object, you can use the dot operator to search that object instead.

Like this:

audioSource.GetComponent<PlayerHealth>(); // Gets a player health script on the same object as the audio source
otherObject.GetComponent<AudioSource>(); // Searches for an audio source on the Other Game Object

The function returns a reference to a component of that type, allowing you to assign a variable automatically.

This is basically the same as dragging the reference to the field in the Inspector, except that it takes place in code.

Like this:

public AudioSource playerAudioSource;

void Awake()
{
    playerAudioSource = otherGameObject.GetComponent<AudioSource>();
}

However, for any of this to work you will still need a reference to the object, or to a component that’s on the object.

So where does that reference come from?

How to get a reference to an object when interacting with it

Generally speaking, the objects and components in your game will either be related to each other or they won’t.

If they’re unrelated, meaning that they’re separate objects that don’t exist in the same hierarchical structure, such as the player and an enemy, then they will still probably interact with each other in some way, such as the enemy physically colliding with the player to cause it damage, or by the player using an object, by clicking it or interacting with it.

Typically, interactions like this are physics-based, where a Raycast, or a collider is used to to detect an interaction with another object, such as an enemy touching the player.

When this happens, you’ll be given a chance to record a reference to the collider that was hit, and through that, call the Get Component function to get a reference to a given component if one exists.

For example, if the enemy collides with an object that has the Player Tag, you can use Get Component to get a reference to its Player Health script and call the Player Hurt function on it.

public class Enemy : MonoBehaviour
{
    [SerializeField] float enemyDamage = 20;

    private void OnTriggerEnter(Collider other)
    {
        if (other.tag == "Player")
        {
            PlayerHealth playerHealth = other.GetComponent<PlayerHealth>();
            playerHealth.PlayerHurt(enemyDamage);
        }
    }
}

However, this only works if the object has a component of that type.

If it doesn’t, the Get Component function will return null, meaning that if you try to access it, you’ll get an error.

To avoid this, it’s usually a good idea to check and see if the reference you tried to set is null or not before trying to use it.

Like this:

public class Enemy : MonoBehaviour
{
    [SerializeField] float enemyDamage = 20;

    private void OnTriggerEnter(Collider other)
    {
        if (other.tag == "Player")
        {
            PlayerHealth playerHealth = other.GetComponent<PlayerHealth>();

            if (playerHealth != null)
            {
                playerHealth.PlayerHurt(enemyDamage);
            }
        }
    }
}

Getting the reference and then checking to see if it’s actually before you use it there can feel a little clunky. 

Luckily, however, in more recent versions of Unity, it’s possible to try to get the component first and then only do something if it exists, all in a single function: Try Get Component.

Like this:

public class Enemy : MonoBehaviour
{
    [SerializeField] float enemyDamage = 20;

    private void OnTriggerEnter(Collider other)
    {
        if (other.tag == "Player")
        {
            if (other.TryGetComponent(out PlayerHealth playerHealth))
            {
                playerHealth.PlayerHurt(enemyDamage);
            }
        }
    }
}

In this example Try Get Component will search the object and, if a Player Health component exists, it will return true and pass the component it finds out to the local variable that’s specified when calling method.

This variable then can be used in the body of the if statement, but only if it actually exists.

If it doesn’t, Try Get Component returns false, and the body of the if condition is never executed, avoiding an error.

Get Component and Try Get Component are ideal when you have a reference to an object and you want to try to access something that’s on it.

But, what if the component you want to access isn’t on that object?

What if it’s on a child object, or on one of its parents?

How to access components in child objects and parent objects

By default, Get Component only searches the object that it’s called on.

But, sometimes, depending on how your objects are structured, you might want to get a reference to something on a related object, such as one of its children or its parent using Get Component in Children or Get Component in Parent.

So how do these functions work?

How to use Get Component in Children

Get Component in Children works in the same way as Get Component except, instead of only checking the specified game object, it checks any child objects as well.

Like this:

public class PlayerHealth : MonoBehaviour
{
    AudioSource playerAudioSource;

    void Start()
    {
        playerAudioSource = GetComponentInChildren<AudioSource>();
    }
}

Note that Get Component in Children checks its own game object and all of its children.

This means that if there’s already a matching component on the game object that calls it, this will be returned and not the component on the child object.

How to use Get Component in Parent

Just like Get Component in Children, you can also get components from parent objects as well.

Like this:

public class PlayerHealth : MonoBehaviour
{
    AudioSource playerAudioSource;

    void Awake()
    {
        playerAudioSource = GetComponentInParent<AudioSource>();
    }
}

Alternatively, if you want to get a component from just the Root Object, and you don’t need to check any other objects along the way, it can sometimes be easier to simply reference that object directly.

This can be done using a transform shortcut that will return the topmost Transform Component in the hierarchy.

Like this:

playerAudioSource = transform.root.GetComponent<AudioSource>();

Just like Get Component in Children, Get Component in Parent checks both the game object it’s called on and the object’s parent.

So if there’s already a matching component on the game object, it will be returned just as if you were using the standard Get Component method.

This can be an issue when you are using multiple components of the same type and you want to be able to distinguish between them.

So how can you get just one component from an object?

How to choose which component is returned when using Get Component

Get Component, Get Component in Children and Get Component in Parent are great for retrieving a single component from another game object.

However…

If you’re using multiple components of the same type on an object, it can be tricky to know which component is actually going to be returned.

By default, when using any of the Get Component methods, Unity will return the first component of that type, from the top down, starting with the game object it’s called on.

That means that if there are two components of the same type, the first one will be returned.

But what if you want to access the second component?

Or the third?

A simple fix is to simply reorder the components so that the one that you want is first.

But, chances are, if you’ve got multiple components of the same type on a game object, you probably need to work with all of them.

For example, stitching audio clips together requires two audio sources to work properly, meaning that you need to have a reference to both of them and toggle between them.  

On solution is to use Get Components to retrieve all of the components of a given type from a game object and then choose the one you want.

So how does that work?

First, create an array of the type of component you want to get a reference to:

Like this:

[SerializeField] AudioSource[] audioSources;

The square brackets after the variable type mark this variable as an Array.

Arrays are a type of collection that allow you to store multiple variables of the same type in a single variable, kind of like a list (but not to be confused with actual Lists in Unity, which are similar to arrays, but can be reordered).

Next, populate the array using GetComponents, GetComponentsInChildren or GetComponentsInParent.

Like this:

audioSources = GetComponents<AudioSource>();

This will add a reference to the array for every matching component that’s found.

Once you’ve filled the array, each element has its own index, starting from Zero:

Unity Array of audio sources

Each Array element has an index, starting from Zero, which is the first.

To access a particular element of the array, simply type the name of the array variable, followed by the index of the element you want to access in square brackets.

Like this:

public class PlayerHealth : MonoBehaviour
{
    public AudioSource[] audioSources;
    public AudioSource playerAudioSource;

    void Start()
    {
        audioSources = GetComponents<AudioSource>();
        playerAudioSource = audioSources[1];
    }
}

In this example, I’ve set the playerAudioSource variable to the second entry in the audio source array.

You’ll notice that I’ve entered number 1 to get the second entry, not 2, this is because the array index starts counting at 0, not 1.

While this method will help to distinguish between multiple components of the same type, it can also be vulnerable to errors, as it will still be possible to change what is returned by simply reordering or removing one of the components.

For this reason, it’s sometimes better to set the reference manually (if that’s an option) or to split components across multiple game objects (if doing so prevents any confusion between them).

And, while it may seem counter-intuitive to create multiple objects to each hold single components, if it helps to avoid errors and makes your project more manageable, then the tiny performance difference is likely to be worth it.

But what about the performance impact of using Get Component in the first place?

You might have heard that using Get Component is bad, that it’s slow and can impact the performance of your game.

So, is it slow?

Is Get Component Slow?

You may have heard that Get Component is slow.

And, technically, yes, it is.

Because Unity is essentially searching through an object’s components every time you use it, it is slower than using an existing, cached reference.

But that doesn’t mean you shouldn’t use it.

The first time I tried to make a game in Unity, I had heard that Get Component was slow and bad.

So I tried not to use it at all.

Which was basically impossible, and meant that I tried to connect objects in unusual ways just to avoid using it.

However, the reality is that you, more than likely, will need to use it at some point, especially if your game involves objects interacting with each other.

Which is fine,

The problem is, how much you use it and how frequently.

It’s generally a good idea to avoid using it repeatedly, such as in Update, Fixed Update, or generally any time you’re using the same reference over and over again.

void FixedUpdate()
{
    // Please don't do this!
    GetComponent<Rigidbody>().AddForce(transform.up * 10);
}

Instead, if you’re going to use a found reference more than once, it’s better to use Get Component to cache it one time and then use the local cached reference in your script.

Like this:

public class Movement : MonoBehaviour
{
    Rigidbody rb;

    void Awake()
    {
        rb = GetComponent<Rigidbody>();
    }

    void FixedUpdate()
    {
        rb.AddForce(transform.up * 10);
    }
}

This is generally better to do in Awake than it is in Start, because Awake is called when a script is first loaded, while Start is called when it is first enabled.

This means that, if you turn an object on while the scene is running, Get Component might be called in the middle of the game, instead of at the start, when it’s much less noticeable.

However, so long as you’re not calling Get Component constantly, or calling it from a large number of objects all at once, you’re unlikely to run into performance issues when using it.

But, is it better to set a reference manually in the Inspector if you can?

Is it better to use Get Component, or set a public variable in the Inspector?

Technically, it’s a little faster to manually set a reference in the Inspector than it is to use Get Component.

But, once you have a reference to a script or a component, both methods perform the same and one isn’t necessarily any better than the other (as long as you’re not calling Get Component frequently, such as in Update).

The only difference you’re likely to notice is a slight increase in loading time if you call Get Component excessively in Awake.

But, for the sake of keeping your project easier to work with, and unless you’re experiencing significant slowdowns, the trade-off is likely to be worth it, since it can be a useful way to set up your scripts and objects automatically.

There’s just one problem.

What happens if you use Get Component to set up a script’s references and the component it needs isn’t there?

When interacting with objects, it makes sense to check if the reference that Get Component returns is null since the object simply might not have a component of that type.

But, when you’re setting an object up, what if it’s supposed to have one?

That’s where Require Component comes in.

How to use Require Component

Require Component is a class attribute that simply forces Unity to check for a certain type of component when adding a script to an object.

It also prevents you from removing a required component from an object if another script requires it to be there.

For example, I could specify that a Randomise Audio script needs an audio source to work.

Like this:

[RequireComponent(typeof(AudioSource))]

This works with Unity’s built-in components and Monobehaviour classes:

[RequireComponent(typeof(PlayerHealth))]

Require Component is a class attribute, so it’s added ahead of the class declaration in square brackets.

Like this:

using UnityEngine;

[RequireComponent(typeof(AudioSource))]
public class RandomiseAudioSource : MonoBehaviour
{
    void Start()
    {
        AudioSource source = GetComponent<AudioSource>();
        source.volume = Random.Range(0.5f, .75f);
    }
}

In this example, when this script is added to an object, if an audio source doesn’t exist, Unity will add one.

And, if you try to remove the audio source while it’s still needed, Unity will stop you.

Unity Require Component Warning

Require Component helps you to avoid sabotaging your own project.

This also works at runtime, except that instead of seeing a warning like in the image above, if you try to remove a component that’s required by a script (by destroying it) it will be disabled, instead of removed.

Using Require Component with Get Component can be a great way to automate the set-up of script components, while still making sure that they have everything they need.

Which can make setting up references on related objects much easier and much more straightforward.

But what if your objects are unrelated? How can you get a reference to a completely different object?

Such as two unrelated objects that never physically interact?

How to find different objects in the Scene

As you start to build the behaviour of your game, chances are, different objects and scripts are going to need to connect to each other in order to work.

And while the easiest way to do this is to create a reference manually in the Inspector, that’s not always possible.

For example, you might instantiate an enemy that needs to find the player.

Or you might need different game systems to be able to set themselves up at the start of a level.

So how can you find and connect with other objects in the scene if they don’t otherwise interact?

One option is to simply search for the object using its Name.

How to find a game object using its name

Finding an object with its name is pretty straightforward, just call the Game Object Find function and pass in the name of the object you want.

Like this:

public class FindObject : MonoBehaviour
{
    public GameObject player;

    void Start()
    {
        player = GameObject.Find("Player");
    }
}

This will return a game object that matches an exact string.

In this case, “Player”.

It’s case-sensitive, so you’ll have to type the name of the object exactly.

It can also be slow, very slow.

In a similar way to Get Component, this method searches through the game objects in the scene and, as a result, is not a very efficient option.

So, while it’s ok to use Find very sparingly, it’s a bad idea to use it frequently, for example inside of your update loop.

But performance isn’t the only drawback.

For example, if the name of the object changes at any time, the script will no longer be able to find that object.

And, if you have multiple objects of the same name in the scene, there’s no guarantee which object will be returned first, as the search order isn’t predictable.

To differentiate between objects of the same name, you can use a forward slash to identify a parent and child object, kind of like you would in a file directory.

Like this:

player = GameObject.Find("PlayerObject/Player");

However, this approach is also vulnerable to name changes as well as object hierarchy changes, both of which will cause this method to stop working.

As a result, you probably want to avoid using Find at all, not just because it’s slow but because it can cause problems that make your project difficult to work with.

So what other options are available for finding a game object in the Scene?

How to find an object using a Tag

Tags in Unity can be useful for identifying a particular object or a type of object.

Such as in a collision, where you might want to check if an object collided with the player or if the player collided with an enemy by checking its tag.

Like this:

private void OnTriggerEnter(Collider other)
{
    if (other.tag == "Player")
    {
        // Do Something
    }
}

Tags can also be used to find and store game object references by using Find With Tag.

First, assign a tag to the game object you want to find.

For example, the Player Tag:

Set a Tag in Unity

You can set an object’s Tag in the Inspector, or create a new one with the Add Tag option.

Next, find the object using the Find With Tag function.

Like this:

player = GameObject.FindWithTag("Player");

Find with tag will return the first object that is found in the Scene with a matching tag.

However…

Just like when searching by name, if your Scene contains multiple objects with the same tag, there’s no guarantee that you’ll get the one you want.

That’s why it’s often helpful to use Find with Tag to search for an object when you know it’s the only one with that tag, such as the player for example.

But what if you want to get a reference to all of the objects in a Scene with a common tag?

Such as an enemy tag, for example?

How to find multiple objects with the same Tag in Unity

Just like Find with Tag, Find Objects with Tag finds objects in the Scene with a certain tag attached, adding them all to an array.

Like this:

public class FindObject : MonoBehaviour
{
    public GameObject[] enemies;

    void Start()
    {
        enemies = GameObject.FindGameObjectsWithTag("Enemy");
    }
}

This is helpful for finding a number of objects of a certain type all at once.

However,

Just like Find with Tag, Find Objects With Tag can also be very slow so, as with any kind of find function, try to use it sparingly.

How to find objects that are the same Type

The Find Objects of Type function can be useful for finding game objects that share the same script or component.

For example, you could use it to find all of the audio sources in a scene .

Like this:

public class FindObject : MonoBehaviour
{
    public AudioSource[] audioSourcesInScene;

    void Start()
    {
        audioSourcesInScene = FindObjectsOfType<AudioSource>();

        foreach(AudioSource audioSource in audioSourcesInScene)
        {
            audioSource.mute = true;
        }
    }
}

Or you could find every object with a health script on it…

Like this:

public class FindObject : MonoBehaviour
{
    public PlayerHealth[] objectsWithHealth;

    void Start()
    {
        objectsWithHealth = FindObjectsOfType<PlayerHealth>();
    }
}

Finding objects in the scene by searching for them can be useful if you can’t create a reference ahead of time, such as by setting it in the Inspector.

But, generally speaking, all search-based functions are going to be slow compared to already having the reference you need.

And while it may not cause you any real problems when your project is small, as your game grows bigger, using methods like these excessively to find and manage collections of objects could start to impact your game’s performance.

But if the alternative is setting the reference yourself, and it’s not possible to do that, such as if the object is created while the game is running, what else can you do? 

Realistically, the kind of information that other scripts may need to get will probably be important variables that lots of scripts might need.

Information such as the score, the player’s position, health or the number of enemies in a scene.

And even if you could connect all of these scripts directly, that could be very difficult to manage.

So what’s the best way to manage all of those variables in a game, and make them available to other scripts too?

Without breaking everything?

Global Variables in Unity

In this context, Global variables generally refer to a variable that has a single value, with a single point of reference and that is accessible from any script, meaning that it’s accessible globally, either from anywhere in the scene or anywhere in the game.

These are different from Localisation Global Variables, which is a feature in the localisation system, now referred to as Persistent Variables, that allows you to combine unchanging data, such as the player’s name or score, into localised text strings.

Compared to different variables on instances of scripts, such as two enemies that each have different health, a global variable keeps track of one single value for all other scripts to reference.

Typically, this will be something unique and important, such as the player’s health, the score or the amount of time remaining.

How do you make a globally accessible variable in Unity?

There are several methods for creating a variable that any script can access.

The simplest method is to use a Static Variable.

Static Variables in Unity

A static variable in Unity is a variable that is shared by all instances of a class.

Meaning that, even if there are multiple instances of a script, on many different objects, they will all share the same static variable value.

To mark a variable as static, simply add the static keyword when declaring it.

Like this:

public class PlayerHealth : MonoBehaviour
{
    public static float health=100;
}

Then, to access the variable, instead of referring to an instance of the class, such as a specific script on a specific object, you can access it via the class itself.

Like this:

Float hp = PlayerHealth.health;

This works because all of the instances share the same value, so you don’t need to identify one script instance in particular, the value is the same on all of them.

This is what allows you to get the variable without a reference, by using the class type instead.

It’s also possible to mark an entire classes as static,

Like this:

public static class PlayerHealth 
{
    public static float health;
    public static float armour;
}

Keep in mind, however, that static classes can’t inherit from MonoBehaviour, meaning that they can’t be attached to objects.

Unlike MonoBehaviour instances, a static class exists outside of the scene, in the project, which makes them useful for utility functions and other code that doesn’t necessarily need to exist inside of a scene as an instance.

But what if you do need the global variable to exist in the scene?

What if it points to an object, such as the player, or an audio manager?

How can you make an instance, global?

Singleton Global Variables

Singletons allow you to make a reference to an in-game object or component accessible to the entire scene.

They can be extremely useful, but only when you use them the right way.

So how do you use them?

A Singleton is, basically, an in-game script that holds a reference to a type of itself.

The reference is public and static, meaning that other scripts can access it through the class name, not an instance.

While the reference, which is an instance, is set by the singleton when it’s created.

Essentially, it sets the reference to itself, but only if the reference hasn’t already been set.

Like this:

public class GameManager : MonoBehaviour
{
    public static GameManager Instance;

    public float playerHealth = 100;
    public int score = 0;
    public float gameTime = 90;

    private void Awake()
    {
        if (Instance != null && Instance != this) 
        { 
            Destroy(this); 
        } 
        else 
        { 
            Instance = this; 
        } 
    }
}

Why is this useful though?

In this example, the Game Manager holds important variables such as the player’s health, the score and how long the game has been running.

Any script can read these by accessing the game manager through the static instance.

Like this:

float health = GameManager.Instance.playerHealth;
float time = GameManager.Instance.gameTime;

Singletons work because they provide global access to a local instance, which is great for connecting scripts with the variables and data that they need to work, even if those objects never interact with each other.

But, singletons are built on statics, and using statics excessively can cause you problems if you use them in the wrong way.

So what is the wrong way?

What’s the right way to use a Static Variable in Unity?

When used in moderation, and for their intended purposes, static variables can be extremely helpful.

This is because they are very convenient, which can also be the problem.

Relying on them too often, or in the wrong way, can cause problems and make your project more difficult to work with.

But how, exactly?

What will actually go wrong if you use statics all over your project?

The general rule of thumb is that a static variable is ok, so long as there will never be more than one of the thing that you’re making static.

And I really do mean never…

For example, it might make sense to store the player’s health in a static variable, right?

Like this:

public static class PlayerHealth
{
    public static float hp=100;
}

It’s then easily accessible by player scripts, enemy scripts and the UI.

However…

If you later decide that you’re going to add a second player, it’ll be difficult to do, since you’ll have already hard coded the static variable path “PlayerHealth.hp” into every single script that needs to access it, it might be difficult for you to then find and change every reference to that variable to get it to work for a second player.

Directly referencing a static health variable would also make it impossible to reuse the script for anything else.

So what’s the answer?

How can you leverage the benefit of globally accessible variables, while still being able to create duplicates of them?

That’s where Scriptable Objects come in.

Scriptable Object variables in Unity

Scriptable Objects are data containers that allow you to store information independently from script instances in the scene.

They work differently from regular classes and static classes but are incredibly useful for building a project that is easy to manage.

So how do they work?

When you create a regular  MonoBehaviour class, the class sits in the Project and instances of it are created in the Scene when they’re added to game objects as components.

Each object’s class instance in the Scene holds its own variable values (member variables) and different objects each have unique data. Such as the health of an individual enemy, for example.

This is great for creating data that is specific to individual objects in a Scene.

However…

When you create a Scriptable Object class, the class acts as a template and individual instances are created inside the project as Assets.

Not in the scene.

Scriptable objects are, basically, script instance assets that sit in your project folder but that can be directly referenced from script components inside of a Scene.

Even if scriptable objects in Unity are new to you, you’ve probably used a similar system before.

For example, audio clips function in a similar way to scriptable objects.

Audio Clips are assets in the project while Audio Sources are components that sit on game objects in the scene.

Audio source components reference audio clips to play them, and changing the audio clip is as easy as dragging a new clip to the audio source’s clip field.

Set Audio Clip in Unity

Scriptable Objects work in a similar way to other assets, such as Audio Clips.

It’s also possible for two different audio sources to reference the same audio clip without needing a reference to each other.

Neither audio source needs to know that the other exists, yet they can both use the same audio clip.

And removing one, makes no difference to the other.

It’s entirely modular.

This is one of the main advantages of scriptable objects… modularity.

So how can you use scriptable objects to create global variables?

How to create a global variable using Scriptable Objects in Unity

Scriptable object global variables work by holding an instance of a variable in a scriptable object asset.

Scripts in the scene can then access the data through a variable of the asset type, meaning that new instances can be created and the script doesn’t have to be changed.

So how does it work?

For example, how could you create a global variable for the player’s health?

First, create a new C# script in the project folder.

This will be the template script that the Scriptable Object assets will derive from.

Create a New Script in Unity

Up until now, you may have only been adding new scripts as components. To create a new script asset in the project without adding it to an object, Right-Click in the Project View and select New C# Script.

Call it FloatVariable, as this Scriptable Object template will form the template for any global float values that you make. It’s also the type of variable that other scripts will use to refer to a variable of this type.

Scriptable Object Template class

Next, open it up and replace MonoBehaviour with ScriptableObject so that it inherits from the Scriptable Object class.

Like this:

public class FloatVariable : ScriptableObject

Then, declare a public float variable called value.

public float value;

Lastly, before the class declaration, add the Create Asset Menu Attribute:

[CreateAssetMenu(menuName = "Float Variable")]

This is what will allow you to create an asset of this type in the project.

Altogether, your script should now look something like this:

using UnityEngine;

[CreateAssetMenu(menuName = "Float Variable")]
public class FloatVariable : ScriptableObject
{
    public float value;
}

Next, you’ll need to create a Float Variable Asset from the scriptable object template, which can be done by right-clicking or using the dropdown Create Menu.

Like this:

Create a Scriptable Object in Unity

Name the newly created Scriptable Object something sensible, like PlayerHP

If you are creating multiple values of this type, this is where you’d distinguish between them, by naming them Player One HP and Player Two HP, for example.

Player Health Scriptable Object

Select the newly created asset, and set a starting value in the Inspector, such as 100, for example.

Set Global Variable in Inspector

Set the starting value in the Inspector, I’ve used 95 here but 100 would probably make more sense.

Scriptable object values are persistent meaning that, unlike member variables, they won’t reset when the scene changes or even when you exit Play Mode. This means you’ll need to manually change the value when you want to reset it.

In this example, to reset the player’s health, you could create a second Float Variable, called DefaultHealth, that stores the starting health of the player, and then simply set the player’s health at the start of the scene using that value as a reference.

So now you’ve created a variable template and a variable instance, how can scripts actually use the value?

To reference the global player health value from a script, create a public FloatVariable in a script. 

Like this:

public FloatVariable playerHealth;

Then, in the Inspector, set the FloatVariable to reference the PlayerHP asset, by dragging it to the field, or by using circle select.

Select a Scriptable Object Variable in the Inspector

Selecting the scriptable object works just like selecting any other asset.

You can then use the variable like any other float value, making sure to remember to use the Dot Operator to access the actual number value that’s stored on the asset.

Like this:

using UnityEngine;

public class PlayerHealth : MonoBehaviour
{
    public FloatVariable playerHealth;

    void Start()
    {
        Debug.Log("The player's health is: " + playerHealth.value);
    }

    void TakeDamage(float damageTaken)
    {
        playerHealth.value -= damageTaken;
    }
}

Keep in mind, that it can be easy to forget to type playerHealth.value when accessing the variable, not just playerHealth, which won’t work.

Now, any script can access the same variable directly, without needing a reference to any other object.

So what’s so great about this?

And how is it any better than a static variable?

Using scriptable objects for global variables can be much more flexible than using static variables.

This is because, while a static reference is written directly into the script, a scriptable object based variable only needs a reference to a variable of that type.

This is useful, as it allows you to swap out data without needing to change the script that’s using it.

Such as for a second player, for example.

All you’d have to do is create another Scriptable Object Float Variable called Player2HP and use that instead.

Now it’s your turn

Now I want to hear from you.

How are you getting references to variables in your game?

Are you dragging them in the Inspector, using Get Component or Scriptable Objects?

And what have you learned about connecting scripts in Unity that you know someone else would find useful?

Whatever it is, let me know by leaving a comment.

John French profile picture

by John French

Game audio professional and a keen amateur developer.

Get Game Development Tips, Straight to Your inbox

Get helpful tips & tricks and master game development basics the easy way, with deep-dive tutorials and guides.

How this content was created

This article was written using first-hand research and experience, without the use of AI. For more information on how Game Dev Beginner articles are written, see my writing policy.

Image credits

Comments

  1. I don’t know if it’s a good idea to show scriptable objects before explaining the importance of private variables for instances and getters/setters.

    It’s like showing the window before explaining there’s a door and a key to open and close access as you need (rather than jumping through the window everytime just because it doesn’t need a key)

    Other than that, amazing explanation

    1. Author

      Thanks for the feedback, the focus of this article is making a connection to another script/variable, which I found to be a nightmare as a beginner, but I accept that properties and particularly public/private are related to this so I may expand the article a bit to include those. Thanks again.

      1. John thank you sooo much for writing this article, like you said making a connection to another script/variable, is a nightmare for Unity c# beginner like myself!

        There is one question I would like to ask and clarify: of all the approaches you mention above, is there an absolute order of priority when thinking which one to go for when communicating with other scripts/gameObjects, like Scriptable Objects is always better than Global Variables, or FindObjectOfType is always better than GetComponent[]? Thanks!

        1. Author

          Thank you! To answer your question, it’s going to be different for every project, and for each use case but I’d generally try to use Find operations as a last resort. But, that said, if using a Find function means keeping your code modular and separate, then it’s appropriate. For advanced tutorials on how to structure code there are some excellent resources on Jason Weimann’s Youtube channel.

  2. Good article for beginners. I think the way that Ryan Hipple uses scriptable objects is really interesting.

    I tried doing things like this but I like to have really generic Actors who have the ability to hit any other Actor with health in a scene so I use the traditional GetComponent().DoDamage(damage) approach.

    I think the SO’s are a really good idea for things like a tower defense or whatever where if an enemy gets to the end, they can call playerLives.ReduceLives() since there’s only one player.

    Going slightly more advanced where you’re talking about what you want to happen when the player is acted upon or does some sort of action: I think you could write something about how important events (delegates) are for creating untangled code.

    Ex. Player class has an OnPlayerDamaged event that gets fired upon taking damage, any class listening for the event (like the PlayerAudio or AudioManager) would then play a damage sound when that event gets invoked.

    1. Author

      Thanks! It’s definitely a separate article but yes, events are super important, especially to avoid polling. I also really like the Scriptable Object even approach (as seen in Ryan’s talk) I found it easier to get started with.

  3. Wow! This is a really good tutorial/explanation. It’s a pretty fundamental topic, but I haven’t yet happened upon a thorough explanation about it such as this. You’re presenting and comparing all options, asking and answering obvious questions, explaining (dis-)advantages…

    This is how you teach, folks!

  4. After reading 3 articles I subscribed. Very useful tutorials, just some slight changes and it will fit in perfectly to my game. Thank you very much! The explanations are very detailed, better than Unity Manual itself lol. I hope you can make a tutorial about data saving pls I saw people using PlayerPrefs and people saying NOT to use PlayerPrefs 🙁

    1. Author

      Thanks! I hadn’t realised that some people didn’t like them, I’ll add it to my TO DO list. Thanks for the tip.

  5. Hi John – I thought this was a really fantastic introduction. Thanks for taking the time to write this. Cheers – Dave

  6. I also suggest researching in the way of IoC. IoC Containers could provide great linking variables from script to script using Injections, but without a lot of dependencies. The best one for Unity is Zenject. But anyway you will use some of the approaches that you described above.

    Good luck!

  7. You are a lifesaver man and your blog is offering the best tips on useful stuff in Unity.
    Thank you, keep up the awesome job!

  8. Hi John,

    I stumbled across your stuff while tinkering with my own game effort…

    I’ve immediately subscribed, and bought one of your assets on the Unity Asset store too (the Ultimate Game Music Collection). Probably not the last.

    Thanks for such clear and methodical explanations and resources… and as for your music… Nordic Landscape – wow.

    Well it’s fantastic to be reminded of why we play games and pursue Art in the first place.

    Thanks for what you’re doing. You deserve every success.

  9. I came in for a quick and dirty fix; searching for how to GetComponent when it is associated with a different GameObject.
    Your explanation is extremely exhaustive. Daunting at times, but invaluable for people with minimal background. So hell yes, thank you!
    And keep it up. Exactly as you do – exhaustive and thorough!

  10. I use the approach of Scriptable Objects all the time because I like the idea of having my data separate from logic and allowing things to listen for when the data changes (instead of having objects linked directly to each other). I also like the flexibility it gives the design team.

    However, I can’t see using Ryan Hipple’s approach exactly as presented. I’ve never seen anyone explain how having SOs just for variables doesn’t have a negative impact on performance. A simple game with 1 player character and 10 enemies could have a 100 variables that need to be tracked just for those objects (let alone everything else).

    No negative reflection on you though. You did a great job explaining the options just think people need to know there is an overhead cost to creating SOs that regular variables don’t have.

    1. Author

      Thanks for your feedback! I hadn’t considered that there could be a performance impact to using scriptable objects but I’ll try and run a test to see what I can find out about it for the article. In reality, there’s probably a middle ground that’s efficient and convenient. Thanks again.

  11. This article has been huge help for me! As a first year of student for game development in Finnish university of applied sciences, this has been eye opening for me. My interests for game development has been in technical side of game production.

    If I may request for you one thing, could you try to make a “beginner” version of how coding logic works. Yes I know that this topic won’t be easily done but give some sort of fundamentals to how logic works in coding. As a first year learning coding I tend to understand API but big part of coding is to find logic for coding.

    1. Author

      Thanks Jukka, and thanks for your feedback, I’ll add it to the list of future articles.

  12. Thank you! I had an additional question that I hope to find an answer to. Is it possible to access the content of a variable that is part of a separate script for the script that you currently need it on. For example, if I am tracking the number of seconds that the player has been in the game as a float, is there any way to access that variable from another script. Thanks again!

    1. Author

      Yes, with the dot operator. For example, if you had a Timer script, with a public float variable called timeElapsed, you could access it like this:

      public Timer timer; void Update() { Debug.Log(Timer.timeElapsed); }

      Is that what you meant?

  13. Thank you very much John. Your website is so much useful for learning Unity. thank you for sharing your knowledge with the world.

  14. thank you greate blog.
    the thing is static variables approach will use less memory than SOs one , cause static vars u can get and set them without having variables that reference to them,
    not like SOs u need to reference them in every class u need them.
    is that right ! how to solve the memory issue of SOs especially if we want to use Ryan Hipple’s approach ?

    1. Author

      Thanks! With the Scriptable Object method, I think that the benefits are more about organisation than performance. Normally, the main benefit of using a Scriptable Object is the reusable data structure, it’s just that Ryan Hipple demonstrated a way to do the same thing in a more granular way with individual variables.

  15. I’m completely new to scripting in Unity. I have been tasked with creating a script to look for every mesh within a project directory, would love to use a dropdown or have user select a directory, and set a variable from on to off on each of the meshes. I am not really sure where to start to even get all meshes let alone how to set a variable on said mesh. I could really use some help with key parts of the code if you would be willing or point me to places to help get me started. Thank you so much…

    1. Author

      Your best bet would probably be the Unity forums, if you haven’t tried posting there already. But I would probably try to separate the issues into different queries (e.g. get meshes, dropdown selection, toggle on/off) since you might get more responses that way.

  16. This article is way too long for something that could have been explained in a couple of sentences. A quick reference near the top would have been nice for people who’s in the middle of programming and just wanted to google a quick answer, because unfortunately this comes up when googling how to reference public variables from other scripts, and this article takes way too long to get to the point.

      1. In hindsight my comment was a bit too critical – There’s a lot of great information in the article and it’s worth the full read when not in the middle of work. I should have added the positives to my initial comment, as the article is indeed very informative.

  17. Hi John,
    I also feel a bit overwhelmed right now because I only googled how to import my public variable in another script and this massive noodle of info came up. BUT I strongly believe learning takes dedication and background info is better than some lonely very specific answer or code snippet. Even if you cant understand or recall everything youve read, its good to have heard it.

    So thank you for putting it all together! Although for my taste, some more text blocks in a smaller font would’ve made it seem less overwhelming maybe.

    I also saw in the comments your website is rated generally useful when it comes to Unity so I will have a deeper look into it! 😀

    Have a nice day!
    Suzan

Leave a Comment