Unity Reset Variable Without Assigning Again
Getting a variable from another script in Unity can be pretty straightforward.
In fact, fifty-fifty if y'all're only just getting started with the basics of 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 yous want to create a connection between different scripts or components, on different objects, that don't otherwise interact?
How can yous keep track of game-wide, global variables, similar a score or the actor'due south health?
And what'due south the best way to do that, without making a mess of your project?
In this article you'll learn the bones methods for accessing a variable on another script. along with some best exercise tips to assistance you lot keep your projection make clean and easy to manage.
What you'll notice on this page:
- How to admission a variable from another script in Unity
- How to manually access a variable using the Inspector
- How to use Get Component in Unity
- How to find different objects in the Scene
- Global variables in Unity
- Static variables in Unity
- How to apply statics to create a Singleton game manager
- Scriptable Object variables in Unity
- How to create a Scriptable Object variable
- Scriptable Object global variables vs static variables
How to admission a variable from another script in Unity
To admission a variable from another script y'all'll first need to get a reference to whatever type of object, class or component you're trying to access.
For example, suppose I'thousand writing a thespian health script for the 2D Knight character below, and I'd similar to play a audio result whenever the player gets hurt.
I have an audio source on the graphic symbol and a Player Hurt function in the script that I tin can utilize to trigger the audio, so how practise I connect the ii?
Earlier I can trigger the audio source component to play from the script, beginning, I need to get a reference to it.
In my player health script, I've created a public audio source reference variable.
Like this:
public class PlayerHealth : MonoBehaviour { public AudioSource playerAudioSource; }
Next, I need to connect that reference to the audio source component on the graphic symbol, so that the script knows which audio source I'grand referring to.
There are several ways I tin practise this just let'southward get-go with the simplest method.
How to manually admission a variable using the Inspector
In this case I've added an audio source component to the player object and have created a public audio source reference variable in my player wellness script.
I've made the audio source variable public, which means and so that it's visible in the Inspector and available to other scripts.
Public vs Private variables in Unity
If the public and private Access Modifiers are new to you then, put only, public variables can be accessed by other scripts and are visible in the Inspector while private variables are non accessible by other scripts and won't show up in the Inspector.
The access modifier is added earlier the data type and, if neither is used, the variable will be private by default…
Here's what it looks like in lawmaking:
public float publicFloat; private string privateFloat; int privateInteger;
You may have already used both public and private variables in tutorials and other examples and, generally, information technology's the simplest way to show a variable in the Inspector or allow some other script to access it.
Notwithstanding… at that place's a little more to it than that.
It is possible to show a individual variable in the Inspector, using Serialize Field,
Similar this:
// This volition show in the inspector [SerializeField] individual bladder playerHealth;
It's also possible to make a variable available to other scripts without also showing it in the Inspector.
Similar this:
// This will not testify in the inspector [HideInInspector] public float playerHealth;
By and large speaking, it'south good practise to simply make a variable public if other scripts demand to access it and, if they don't, to keep information technology private.
If, however, other scripts do not need to access it, merely you lot do demand to see it in the inspector then you can apply Serialize Field instead.
This keeps the variable private only makes it visible in the Inspector.
However… for the sake of keeping examples simple, in many tutorials and examples, you volition often run across a variable marked equally public for the purpose of editing it in the Inspector.
In my example, I've used a public variable because I will want to be able to access it from another script and then that I can prepare the variable in the Inspector, which is exactly what I'm going to do next.
Fix the variable in the Inspector
Both the script and the audio source are attached to the same game object, which in this case is the role player, and connecting the 2 is as easy as dragging the audio source component to the player sound source field on the script component.
Similar this:
I could also utilize the circle select tool, which will listing all of the game objects in the Scene with components that match the reference type, in this example, whatever game objects with sound sources attached.
Like this:
At present that I have a cached reference to the audio source component I can admission its all of its public properties and methods.
Similar this:
public class PlayerHealth : MonoBehaviour { public AudioSource playerAudioSource; void PlayerHurt() { // Deal harm! playerAudioSource.Play(); } }
I tin use the same method to access script instances every bit well.
Just similar when creating an sound source reference variable, a script reference variable works in the aforementioned way.
Instead of "AudioSource", nonetheless, but type the name of the class as the variable'due south type.
For example, I could create a reference to an instance of the "PlayerHealth" script I just wrote.
Like this:
public PlayerHealth playerHealth;
Just like with the audio source component, I can fix this variable in the Inspector to reference any example of any thespian health script in the Scene, and use that connection to access its public variables and methods.
Like this:
public class SomeOtherScript : MonoBehaviour { public PlayerHealth playerHealth; void Offset() { playerHealth.playerAudioSource.Play(); } }
This method of creating and assigning references manually is like shooting fish in a barrel and straightforward.
And, chances are, if you've done anything at all in Unity, you lot've already created references like this before.
But what if yous tin't drag and drop the object in the Inspector?
This might be because the component is created at runtime, or merely doesn't exist yet.
Or information technology may be that the field is private and isn't visible in the Inspector.
And while it is possible to serialise private fields, it may be that you lot have no need to modify the variable from the Inspector and want to keep it hidden for the sake of keeping the script unproblematic and piece of cake to manage.
Whatever the reason, how can you get a reference to something, without assigning it manually?
One choice is to utilise Get Component…
How to apply Get Component in Unity
Get Component is a method for finding a specific type of component.
It allows you to search for a specified type of component on i or a number of game objects and get a reference to information technology.
This is particularly useful for getting references to components that are on the aforementioned object as the calling script, but information technology can also be used to search for components on other game objects every bit well.
And so how does it work?
Become Component takes a generic type which, if you lot await at the code beneath, is entered in identify of the T in angled brackets.
GetComponent<T>();
If the angled brackets "<T>" are new to you, don't worry.
In this example, they simply hateful that Get Component can search for any type of component and that you'll need to specify the blazon in the angled brackets when using information technology.
Simply replace "T" with whatsoever component type (or course name) y'all're trying to find.
Similar this, to find an Audio Source component:
GetComponent<AudioSource>();
In my previous example, I created a public reference to the thespian's audio source manually, by setting information technology in the Inspector.
Using Get Component, I can prepare the reference I need in Showtime without exposing it as a public variable.
Similar this:
public class PlayerHealth : MonoBehaviour { AudioSource playerAudioSource; void Start() { playerAudioSource = GetComponent<AudioSource>(); } }
You might have noticed that I didn't specify what game object the component is attached to, I only typed "GetComponent…".
This works because the component I want is on the same game object as the script.
But what if it's non?
What if information technology'south on a child object, or a parent object, or somewhere else entirely?
Become Component from a different object
To get a component from a different game object, you will start need a reference to that game object (more on how to do that later).
GameObject otherGameObject;
Once you have it, Go Component can be chosen using the game object's reference and the dot operator.
Like this:
public course PlayerHealth : MonoBehaviour { public AudioSource playerAudioSource; public GameObject otherGameObject; void Outset() { playerAudioSource = otherGameObject.GetComponent<AudioSource>(); } }
For this to piece of work, you will usually need to have a reference to the object that the component is attached to, except if the component is on a child object or the object's parent.
In which example, it's possible to apply Go Component in Children or Get Component in Parent to get the component without having a reference to its object first.
Hither's how you do information technology.
How to utilize Become Component in Children
Get Component in Children works in the aforementioned way equally Get Component except, instead of but checking the specified game object, it checks any kid objects likewise.
Like this:
public class PlayerHealth : MonoBehaviour { AudioSource playerAudioSource; void Beginning() { playerAudioSource = GetComponentInChildren<AudioSource>(); } }
Notation that Become Component in Children checks its own game object and all 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 similar Get Component in Children, you lot can likewise become components from parent objects too!
Similar this:
using System.Collections; using System.Collections.Generic; using UnityEngine; public grade PlayerHealth : MonoBehaviour { public AudioSource playerAudioSource; void Outset() { playerAudioSource = GetComponentInParent<AudioSource>(); } }
Just like Get Component in Children, Become Component in Parent checks both the game object it'southward called on and the object's parent.
So if at that place'south already a matching component on the game object, it will exist returned simply as if you were using the standard Get Component method.
This can be an issue when you are using multiple components of the same blazon and yous want to be able to distinguish between them.
Luckily there'south a solution for that besides…
How to get the second component on a game object (managing multiple components)
Get Component, Go Component in Children and Get Component in Parent are great for retrieving a unmarried component from another game object.
Nevertheless…
If you lot're using multiple components of the same type on an object, information technology tin can be tricky to know which component is actually going to be retrieved.
By default, when using whatever of the Become Component methods, Unity volition return the first component of that type, from the top downward, starting with the game object it'south called on.
That means that if there are 2 components of the aforementioned blazon, the first 1 volition be returned.
Simply what if you desire to access the second component?
1 method is to simply reorder the components so that the one that you want is showtime.
And if that works for you, and so do that.
Nevertheless…
If other objects are accessing the component in the same manner, reordering them could cause problems for other scripts that may rely on a certain object club.
Alternatively, you can utilise Get Components to recollect all of the components of a given type from the game object and then choose from those.
Here's how it works…
First, create an assortment of the blazon of component you lot're trying to retrieve:
Like this:
public AudioSource[] audioSources;
Note the foursquare brackets subsequently the variable blazon, which marker information technology as an Array.
If yous're non familiar with Arrays, they simply let you lot to shop multiple variables of the aforementioned blazon in a unmarried assortment 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 together a reference to the array for every matching component that'due south found.
Once you've filled the array, each element has its own index, starting from 0:
To access a particular chemical element of the array, simply blazon the name of the array variable, followed past the index of the element you want to admission 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 instance, I've ready the playerAudioSource variable to the second entry in the audio source assortment.
Y'all'll notice that I've entered number 1 to become the 2nd entry, not 2. This is because the array index starts counting at 0, non 1.
While this method will help to distinguish between multiple components of the same type, it can also be vulnerable to errors, as information technology will notwithstanding be possible to change what is returned past simply reordering or removing one of the components.
For this reason, it's sometimes ameliorate to ready the reference manually (if that's an option) or to split components beyond multiple game objects (if doing so prevents any confusion between them).
And, while information technology may seem counter-intuitive to create multiple objects to each agree single components, if information technology helps to avoid errors and makes your project more manageable, and so the tiny performance divergence is probable to be worth information technology.
Is Get Component Deadening?
Using Get Component tin can exist a helpful way of caching references.
Still…
Because Unity is essentially searching through an object's components every time you lot use information technology, it is slower than using an existing, cached reference.
That's why it's a skillful idea to use Go Component as infrequently every bit possible.
Such as in one case, in Showtime, to cache a reference to a component, or occasionally in the game when setting upward new objects.
However, so long as you're non calling Get Component in Update, or calling it from a large number of objects all at once, you lot're unlikely to run into functioning problems when using information technology.
Become Component vs setting a public variable in the Inspector (which to use)
Then… which is the better option for getting a reference to component or script?
Is it Get Component, or should yous manually prepare a public variable in the Inspector?
Generally speaking, once you have a reference to a script or a component, both methods perform the same and 1 isn't necessarily any better than the other (equally long every bit you're not calling Go Component frequently, due east.g. in Update).
And then, when deciding which method to use, it's improve to consider which will be easier for y'all to manage.
For case… if y'all're creating a game object Prefab, and are using several dissimilar parts, each with their own scripts that refer to other parts and Components of the object every bit a whole, there's no real sense in using Become Component to connect everything together. It's more than convenient, and probably more manageable, to fix up the connections yourself, saving them in the finished Prefab.
Alternatively, however, if you've created a reusable script component that is designed to perform a unmarried task when it's dropped onto a game object, Get Component tin can be a useful manner of automatically setting it up.
Say, for example, I wanted to create a script that randomises an sound source'due south settings in Start. Using Become Component to prepare the sound source automatically would remove an unnecessary step.
I could and then simply add information technology to whatever object with an sound source on it and let the script set itself upwards.
Handy, right?
There'south merely one problem.
If I forget to add an audio source to the object when adding my script, it's going to try to get something that just isn't in that location, causing an error.
And so if I want to utilise Go Component to automate the gear up up of a script, how can I make sure it has everything it needs?
That'due south where Crave Component comes in.
How to employ Require Component
Crave Component is a class aspect that only forces Unity to check for a certain type of component when adding the script to an object.
It besides prevents you from removing a required component from an object if another script requires it to be in that location.
For instance, I can specify that my Randomise Audio script needs an audio source to work.
Like this:
[RequireComponent(typeof(AudioSource))]
This also works with other types of component and, of form, other script classes:
[RequireComponent(typeof(PlayerHealth))]
Require Component is a class attribute, and so it's added ahead of the course declaration in square brackets.
Similar this:
using UnityEngine; [RequireComponent(typeof(AudioSource))] public grade RandomiseAudioSource : MonoBehaviour { // Start is chosen before the first frame update void Start() { AudioSource source = GetComponent<AudioSource>(); source.volume = Random.Range(0.5f, .75f); } }
Now when calculation this Script to an object, if an audio source doesn't exist, 1 will be added for me.
And, if I endeavour to remove that audio source while it'south notwithstanding needed, Unity will terminate me.
This too works at runtime, except that instead of seeing a alert similar in the epitome above, if yous try to destroy a component that's required by a script, it will be disabled, instead of removed.
Remember, yet, that Require Component only works when calculation or removing the script.
So, for example, if y'all add a script to a game object and then, afterwards, give information technology a Require Component aspect, Unity will not check for that component, which could and so cause an error.
Using Require Component with Get Component is a great mode of automating the prepare of script components, while still making certain that they have everything they demand.
And this can make setting up references on closely linked objects much easier and much more straightforward.
But…
How tin can yous get a reference to a completely different object?
Similar the player, or an enemy, or whatsoever number of entirely separate game components.
Without making a mess of your projection.
Finding different objects in the Scene
As y'all start to build the different parts of your game y'all volition, no doubt, need each part to connect and communicate with each other.
And while the easiest manner to do this is to set information technology upwards manually in the Inspector, that'due south non e'er possible.
For example, you might instantiate an enemy that needs to find the role player.
Or you might need unlike game systems to be able to ready themselves upwardly at the start of a level.
Luckily though, at that place are plenty of options available for finding objects in the Scene.
Let'southward kickoff with some basic options.
Find GameObject by Name
One simple method of getting a reference to an object is with its proper name.
Like this:
public form FindObject : MonoBehaviour { public GameObject player; void Start() { player = GameObject.Find("Histrion"); } }
This volition render a game object that matches an exact string.
In this case, "Player".
Information technology'south case sensitive, then you'll take to blazon the name of the object exactly.
It can also be tiresome…
Similar to Become Component, this method searches game objects in the Scene and, equally such, it's non the almost efficient option.
And then, while it's ok to use Observe sparingly, information technology's a bad idea to utilize information technology frequently, for example inside of your update loop.
And while it is like shooting fish in a barrel, and can be very user-friendly, finding an object past its name has a few drawbacks.
For example, if the proper noun of the object changes at any time, the script will no longer be able to observe it.
And, if yous have multiple objects of the same name in the Scene, there's no guarantee which object volition be returned.
This is different other searches, such every bit Get Component, which is more predictable (searching top downward).
To differentiate betwixt objects of the aforementioned name, y'all can use a forward slash to identify a parent and child object, kind of like y'all would in a file directory.
Like this:
player = GameObject.Detect("PlayerObject/Player");
Withal, this arroyo is also vulnerable to name changes equally well every bit object bureaucracy changes, both of which will cause this method to terminate working.
Then… what other options are in that location for finding a game object elsewhere in the Scene?
How to find an object by its tag in Unity
Tags in Unity tin can be helpful for telling detail objects apart.
Such as in a standoff, where you might want to check if an object collided with the player or if the player collided with an enemy past checking its tag.
Like this:
private void OnTriggerEnter(Collider other) { if (other.tag == "Player") { // Exercise Something } }
That'southward not all though,
Tags can also be used to discover and shop game object references past using Find With Tag.
Start assign a tag to the game object you want to observe.
For case, the Thespian Tag:
You can also create new tags using the Add Tag… option.
Next discover the object using Notice With Tag.
Like this:
player = GameObject.FindWithTag("Player");
Find with tag will return the first object that is institute in the Scene with a matching tag.
However…
Just similar when searching past proper name, if your Scene contains multiple objects with the same tag, there's no guarantee that you'll get the one you want.
That'due south why it's often helpful to use Detect with Tag to search for an object when you know it'southward the only 1 with that tag, such as the actor for instance.
But what if you want to become a reference to all of the objects in a Scene with a common tag?
An enemy tag for instance…
How to go multiple objects with tags
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 grade FindObject : MonoBehaviour { public GameObject[] enemies; void Kickoff() { enemies = GameObject.FindGameObjectsWithTag("Enemy"); } }
This is helpful for finding a number of objects of a sure type at once.
Yet…
Just similar Find with Tag, Discover Objects With Tag tin can likewise be slow, and so it's usually all-time to avoid using it frequently, such every bit in an Update loop.
Observe Objects of Type
Discover Objects of Type can be useful for finding game objects that share the same script or component.
For case you could use it to find all of the sound sources in a Scene .
Like this:
public grade FindObject : MonoBehaviour { public AudioSource[] audioSourcesInScene; void Start() { audioSourcesInScene = FindObjectsOfType<AudioSource>(); foreach(AudioSource audioSource in audioSourcesInScene) { audioSource.mute = true; } } }
This script volition find every audio source in the Scene and mute each 1.
Or you could find every object with a health script on information technology…
Similar this:
public grade FindObject : MonoBehaviour { public PlayerHealth[] objectsWithHealth; void Start() { objectsWithHealth = FindObjectsOfType<PlayerHealth>(); } }
Any y'all demand it for, Find Objects of Blazon can be a quick and piece of cake mode to manage a group of objects that all share the same functionality.
But… simply as with any function that involves searching the Scene, this method tin exist slow.
And while it may not crusade you lot any real problems when your projection is pocket-sized, as your game grows bigger, using this method to detect and manage collections of objects tin can be dull and difficult to manage.
Using the previous example, instead of finding every Enemy, or every object with Health, it tin can be easier to, instead, accept objects add themselves to a Listing that other objects and scripts can then check.
And that's not all. You volition likely discover that, equally you build your project, more and more scripts need to share the same pieces of information.
Information such as the score, the player's position, health or the number of enemies in a Scene.
To accept each script connected to every other script it needs to employ could become difficult to manage very, very speedily.
Then what's the all-time way to manage all of those variables in a game, and make them available to other scripts besides?
Without breaking everything.
Global variables in Unity
What are global variables in Unity?
Global variables in Unity by and large refer to a variable that has a single value, a single signal of reference and that is accessible from whatever script.
Compared to variable instances on regular scripts, which may accept many different instances each with different values on multiple game objects, a global variable's purpose is to proceed runway of a single variable's value for other scripts to reference.
You might use this for the role player's wellness, the score, time remaining or other game-critical values.
How do you brand a global variable in Unity?
There are several methods for creating global variables in Unity.
The simplest method for creating a global variable is to utilise a static variable.
Static variables in Unity
A static variable in Unity is a variable that is shared by all instances of a class.
To mark a variable as static in Unity, simply add the static keyword when declaring information technology.
Like this:
public form PlayerHealth : MonoBehaviour { public static float health=100; }
And then, to access the variable, instead of referring to an instance of the class, yous tin access it via the class itself.
Like this:
Float hp = PlayerHealth.health;
This works considering the variable is public and static, so even if there are many instances of this script, they volition all share the same value.
Information technology's also possible to marking an entire classes as static,
Similar this:
public static class PlayerHealth { public static float wellness; public static float armour; }
Note, however, that as static classes can't derive from MonoBehaviour, then you'll need to remove the normal ": MonoBehaviour" inheritance from the end of the class announcement.
You'd also be forgiven for thinking that this automatically makes every variable within the grade static. It doesn't.
Instead, marking a class every bit static simply means that information technology cannot exist instantiated in the Scene.
You'll still need to mark individual variables and methods inside the class as static for them to piece of work as you wait.
Using statics to create a Singleton game manager
1 method of using static variables to manage global references and values is to create a Singleton game manager.
A Singleton uses a single, static, point of entry via a static instance reference.
That manner other scripts can admission the Singleton, and its variables, without getting a reference to it first.
For example, you lot could create a script called Game Manager that holds variables such every bit the score, game time and other important values, and add it to an object in the Scene.
The Game Manager script then keeps a static reference to itself, which is accessible to other scripts.
Similar this:
public class GameManager : MonoBehaviour { public static GameManager Case { get; private set; } public float playerHealth=100; public bladder gameTime = 90; individual void Awake() { Instance = this; } }
Notice the Become; Private Set, lines later the variable declaration? Get and Set functions plow a variable into a Property which, simply put, adds a layer of control over how a variable is accessed past other scripts. They can be used to run additional code when setting or getting a variable or, in this case, to preclude the other scripts from setting the example.
This script needs to be added to an object in the Scene in order to work, and so the class itself isn't static, just its instance reference.
Once it is, nonetheless, other scripts can access the manager'southward public variables by referencing the Game Managing director form and its Case.
Like this:
void Start() { Debug.Log(GameManager.Case.playerHealth); Debug.Log(GameManager.Case.gameTime); }
This is a very basic example of the Singleton design blueprint. In practice, when using Singletons, some extra care should exist taken to manage the accessibility of variables and to avoid creating duplicate game director instances in the Scene. See the links section at the cease of this article for some more advanced information almost using Singletons.
When is it ok to utilize static variables in Unity?
When used in moderation, and for their intended purposes, static classes, references and variables can be extremely helpful.
Yet…
While they tin be very convenient, relying on them too oft, or in the wrong way, tin can crusade issues.
Why?
Well, information technology depends on how you lot're using them.
You may have heard that it'south generally bad exercise to use statics (and Singletons for that matter).
But what'due south the deal?
Why tin't you use static variables?
When is it ok to utilise them?
What will actually go incorrect if you do?
One of the main reasons for avoiding statics is to prevent encapsulation and dependency issues, given that, unlike class instances, statics are not specific to any ane object or scene but are, instead, attainable to the entire project.
This is, of grade, exactly why using a static variable can be very user-friendly, you tin access it from anywhere.
Just, the same matter that makes a static easy to use, tin can besides crusade problems as your project grows.
For case, carelessly connecting multiple scripts together via static references, simply because information technology's an easy mode to practice it, could cause unwanted dependencies between those scripts.
Removing one could break another, or could simply become difficult to manage.
And, while there are legitimate reasons for using statics, as a project gets larger, using them carelessly in this way can cause bug that are difficult to find, test or gear up.
Should y'all never utilise static variables?
In reality, using static variables sparingly isn't necessarily a problem, particularly if your project is small, and then long as you empathize the right way to utilise them.
So what is the right way to use them?
Mostly, information technology's ok to apply a static variable for something if there volition never exist more one of it.
And I really do mean never…
For case, it might make sense to shop the thespian's health in a static variable, correct?
Like this:
public static form PlayerHealth { public static float hp=100; }
It's then hands accessible by role player scripts, enemy scripts and the UI.
However…
If you later decide that you're going to add together co-op multiplayer support to your game, and y'all've hard coded the static variable path "PlayerHealth.hp" into every unmarried script that needs to access it, it might be hard for y'all to then find and change every reference to that variable to get information technology to work for a second actor.
Likewise, a health script as a reusable component would ideally be used for players and enemies alike.
Directly referencing a static wellness variable makes it impossible to reuse the script for anything else.
And then how tin can you leverage the do good of globally accessible variables, while keeping it modular?
That's where Scriptable Objects come in…
Scriptable Object variables in Unity
Scriptable Objects in Unity are information containers that let 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 like shooting fish in a barrel to manage.
They are amazingly useful.
No… actually!
Then how do they work?
When yous create a regular course, the class sits in the Project and instances of that class are created in the Scene when they're added to game objects every bit components.
Each object's form instance in the Scene holds its own variable values (member variables) and different objects each accept unique data. Such as the health of an enemy, for instance.
This is great for creating data that is specific to objects in a Scene.
However…
When you create a Scriptable Object form, the class acts as a template and private instances are created inside the Project, in the Assets Folder.
Not in the Scene.
Scriptable Objects are, essentially, avails that sit in your project folder but that can be directly referenced from script instances in the Scene.
Now…
If I've lost you, don't worry, because you've probably already used assets in this style before.
For example, audio clips function in a similar style to Scriptable Objects.
Sound clips are avails in the Project while audio sources are components that sit on game objects in the Scene.
Sound source components reference audio clips to play them, and changing the audio clip is as like shooting fish in a barrel as dragging a new prune to the sound source'south clip field.
It'southward 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 tin both utilise the aforementioned sound prune.
And removing one, makes no difference to the other.
It'due south entirely modular.
Which is the power of Scriptable Objects… modularity.
So how can you leverage the ability of Scriptable Objects to manage object references and global variables?
Hither's how to do it…
How to create a global variable using Scriptable Objects in Unity
In the post-obit example, I'k going to create a player health value over again, except this time using a Scriptable Object:
Full disclosure, and credit where it'due south due, I first discovered this method of using Scriptable Objects as variables from a Unite talk by Ryan Hipple. Whereas I'm using Scriptable Objects to create bones global variables, Ryan's talk highlights, in depth, how yous tin can leverage Scriptable Objects to structure your game in a very modular way. I strongly recommend watching it in total and I'll leave a link to the video at the finish of this article.
Here'due south how it works…
First I demand to create a template script that the Scriptable Object assets volition derive from.
1. Create a new C# script in the Project Binder:
-
-
-
-
- Call it FloatVariable, this Scriptable Object template volition form the template for whatever Bladder Variable Scriptable Objects yous brand.
-
-
-
-
-
-
-
- Open information technology upwards and replace MonoBehaviour with ScriptableObject and so that information technology inherits from the Scriptable Object class.
-
-
-
public grade FloatVariable : ScriptableObject
-
-
-
-
- Next, declare a public bladder variable chosen value.
-
-
-
public bladder value;
-
-
-
-
- Lastly, earlier the class announcement, add a line that reads:
-
-
-
[CreateAssetMenu(menuName = "Bladder Variable")]
This allows assets of this Scriptable Object to exist created from the Projection view'south Right Click Menu. This is important as, without this, you won't hands be able to create Scriptable Objects from this template.
Your script should at present look something like this:
using UnityEngine; [CreateAssetMenu(menuName = "Float Variable")] public class FloatVariable : ScriptableObject { public float value; }
That's all that's needed to create the Template, now to create Script Instances that tin can hold unique data.
2. Next, create a Float variable asset from the Scriptable Object template
-
-
-
-
- In the Project View right click and select Create > Float Variable
-
-
-
-
-
-
-
- Proper noun the newly created Scriptable Object something sensible, similar PlayerHP
-
-
-
-
-
-
-
- Select the newly created Scriptable Object, and set a starting value in the Inspector, due east.g 100.
-
-
-
Scriptable Object values, unlike member variables, do not reset when the Scene changes or fifty-fifty when yous exit Play Mode. This means you'll demand to manually change the value when you want to reset information technology.
In this example, to reset the thespian's health, yous could create a 2d Float Variable, called DefaultHealth, that stores the starting health of the player, and so simply set the player's wellness at the start of the Scene using that value equally a reference.
Then at present you've created a variable template and a variable instance, how can other scripts use that value?
iii. Reference the Scriptable Object from scripts in the Scene
Finally, to reference the global role player health value from any script:
-
-
-
-
- Create a public FloatVariable variable on any other script. Phone call information technology playerHealth, simply as an example (the name does non need to lucifer the Scriptable Object)
-
-
-
public FloatVariable playerHealth;
-
-
-
-
- In the Inspector, gear up the FloatVariable to reference the PlayerHP Scriptable Object (click and drag it, or use circumvolve select).
-
-
-
Yous can and so use the variable similar whatsoever other bladder, making sure to call up to utilize the Dot Operator to admission its actual value.
Similar this:
using UnityEngine; public form PlayerHealth : MonoBehaviour { public FloatVariable playerHealth; void Start() { Debug.Log("The actor'due south wellness is: " + playerHealth.value); } void TakeDamage(float damageTaken) { playerHealth.value -= damageTaken; } }
Tip: Remember to type playerHealth.value when accessing the variable, not simply playerHealth, which won't work.
Now, whatsoever script can admission the same variable straight, without needing a reference to any other object.
And then what's and then slap-up about this?
And how is it any ameliorate than a static variable?
I'll explicate…
Scriptable Object global variables vs static variables
Using Scriptable Objects for global variables tin be much, much more than 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.
How is that better?
In the example above, I used a Scriptable Object variable to keep runway of the player's health, in this case using an case of my Bladder Variable template.
Then, any time I want to access the player's health (from any Script in the projection) I merely make a reference to a Bladder Variable Scriptable Object and so driblet in the PlayerHP example.
Like this:
public FloatVariable playerHealth;
What's great well-nigh this is that, only similar swapping out sound clips, I can employ whatever Float Variable Scriptable Object in its place.
For instance for a second player.
All I'd take to exercise is create some other Scriptable Object Float Variable called Player2HP and employ that instead.
All without e'er editing the script.
Information technology'due south this flexibility and modularity, that makes Scriptable Object variables and so incredibly useful.
Now information technology'south your turn
Now I desire to hear from you.
How will you use these tips in your project?
What's worked well for yous in the by?
What hasn't? And what did you wish you knew when you lot first got started in Unity.
Whatever it is, let me know by leaving a comment below.
From the experts:
Ryan Hipple explains how to avoid Singletons and use Scriptable Objects as variables:
Jason Weimann describes the different types of Singleton Patterns he uses and some common pitfalls to avoid:
My favourite time-saving Unity avails
Rewired (the all-time input management organization)
Rewired is an input management asset that extends Unity's default input system, the Input Manager, adding much needed improvements and support for modern devices. Put just, it's much more avant-garde than the default Input Manager and more reliable than Unity'southward new Input Organization. When I tested both systems, I institute Rewired to be surprisingly like shooting fish in a barrel to utilize and fully featured, so I can understand why everyone loves information technology.
DOTween Pro (should exist built into Unity)
An asset and so useful, it should already be built into Unity. Except it'due south not. DOTween Pro is an animation and timing tool that allows you to animate annihilation in Unity. Yous can move, fade, scale, rotate without writing Coroutines or Lerp functions.
Easy Save (in that location'south no reason not to use it)
Easy Save makes managing game saves and file serialization extremely piece of cake in Unity. So much so that, for the time it would take to build a save arrangement, vs the cost of buying Easy Salve, I don't recommend making your own save system since Like shooting fish in a barrel Save already exists.
Prototype credits
-
-
-
-
- Flat Platformer Template by Bulat
- Icons fabricated by Freepik from world wide web.flaticon.com
-
-
-
Source: https://gamedevbeginner.com/how-to-get-a-variable-from-another-script-in-unity-the-right-way/
0 Response to "Unity Reset Variable Without Assigning Again"
Post a Comment