Unity learning path

This article gives beginners an overview of the “noob to pro” learning path to Unity. This list is a starting point for anyone, who has no prior knowledge of game engines or development environments.

If you already have Unity up and running and are familiar with the most basic things, skip ahead to the Learning Resources section.

Step 1 – Getting Unity and the right mindset

Download Unity 5 from here and install it.

Open Unity and select the Get started tab to view a quick introduction video.

Before diving into the editor, I recommend watching the Your First Game video series by Extra Credits to get first advice on how to start. Many of their tips can help beginners avoid common pitfalls and frustration.

Start small and build projects, which you can complete within a few days.

Step 2 – First steps in the editor

To get started in the editor, create a new Unity project.

Create your first project in Unity.
Create your first project in Unity.

 

You do not need to create a new folder for your project. Unity automatically creates one from the project name.

Next, you might want to chose a different window layout:

Unity window layouts.
Unity window layouts.

Select the Layout panel from the top right or hit Window > Layouts and then select 2 by 3. This view shows you the most typical window tabs in Unity.

What you are looking right now is all part of a Scene. At the moment, you haven’t saved your scene, therefore it it untitled. Take a look at the Unity application frame:

Untitled Unity scene in your project.
Unity application frame showing scene title, project name and build target.

 

Click File > Save Scene to save your scene and thereby creating your first Asset.

The Project panel shows you all assets that are currently stored in your project.

Unity's project view.
Unity’s project view.

 

Click the tab menu at the top right and select One Column Layout if you want to browser assets in tree view. All assets, including scenes, images, scenes, models, animations and scripts, are stored in a folder called Assets.

Now, select the Main Camera GameObject from the Hierarchy.

Unity's hierarchy panel.
Unity’s hierarchy panel.

 

The Hierarchy panel shows all GameObjects that are part of the current scene. In Unity, everything is a GameObject: models, scripts, lights, cameras, etc.

A GameObject alone does nothing at all. To have functionality, it must contain Components. You can view attached Components of any GameObject in the Inspector:

The Unity Inspector shows Components.
The Unity Inspector shows Components.

 

If you want to find out what a certain component does, click the blue book icon. This will take you straight to the corresponding page in the Unity manual.

The Unity Manual will be your main resource for learning everything you need to know about the game engine.

Step 3 – Using the official learning resources

Unity offers us great documentation to learn just about everything: the manual, the scripting reference, video tutorials and live trainings.

These pages and videos alone are more than you can ever read, so I will try and give you a guide where to begin:

After this introduction and some playing around you should be able to create scenes with simple objects.

From now on you will want to focus on specific topics, but to get started making your first game, you should learn about scripting:

My favorite tutorial:

 

Now you’re ready to start a real project:

Once you’re done or if you have problems, watch one of the scripting videos for detailed information about specific topics:

I encourage you to go through those videos in order, but also follow along with your own scripting experiments.

Put all beginner techniques to use in this great Unity project:

Finally, move away from noob topics and create your first intermediate game:

Step 4 – Pick your own topics from recommendations

Nobody can be good at everything, so after stepping from your beginner’s pedestal, you should focus on certain topics more than others. In any case, I still recommend to at least glance over all topics from the official Unity documentation, just so you know what exists..

Some of my personal favorites:

Step 5 – Beyond the basics

Up to this point, I’ve only linked resources which teach you how to use Unity, but not how to make real-world games. In fact, going from knowing how Unity components work to knowing how to make a great game is the difficult part.

Be aware that the nature of tutorials is to be concise, but real-world games are very complicated. You can only bridge this by creating your own projects and take away experience with every finished game.

You may also want to buy a book from a professional game developer and look at how they design their projects in the business world.

 

Creating timers in Unity

One of the most common things to do in game programming is to wait for a certain period of time before calling an event. In this article you will find several types of timers in Unity explained and when to use them.

Simple repeating timer in Update()

Let’s create the most basic timer that does something every x seconds:

  • waitTime means how long to wait in between action calls and can be overriden via the inspector.
  • timer is used to store the time that has passed.
  • Update() is called every frame, so we add our deltaTime to our timer in every Update() cycle. The property deltaTime returns how much time in seconds has passed since the last frame.
  • If our timer has risen above our waiting time, a method is called.
  • In place of the print() statement, you can call whatever action needs to repeat.
  • We restart the timer by resetting it to zero.

 

DeltaTime in Unity.
DeltaTime in Unity.

 

DeltaTime in Unity gives us the length of the previous frame, which if you’re running at 60 fps is 1/60 of a second, or about 0.016 seconds.

The basic timer shown above is easy and fast, but your code might end up being cluttered, because the timer is not sealed off in it’s own method.

Here’s another example, that can be turned on and off:

Toggle timer via Update()

 

First, OnTriggerEnter() is called, whenever our CannonBall enters the trigger area  of any GameObject tagged “Player”. This sets the boolean timerRunning true.

The Update() loop is checking every frame for timerRunning and when it becomes true, it calls the BombTimer method. Our timer waits for waitTime to pass and then does something.

Lastly, the timer resets itself until another Player trigger is entered.

Unity offers a few helper functions that can call methods after a period a time or repeat actions:

Destroy an object after x seconds

You can use the Destroy() method from MonoBehaviour and pass in a float parameter to delay it. Note, that you only want to call this method once, not in Update().

Invoking a method after x seconds or repeating it

The Invoke() method takes a method name as a string and the waitTime as a float parameter. This helper function is very convenient, because of it’s clean syntax, but be aware, that invoking methods via string is much slower than calling them directly. Only use this for testing or when performance isn’t an issue.

You can also use InvokeRepeating() to wait for a period of time and then repeat the method call every x seconds:

Again, the Invoke() methods are convenient but slow.

You can stop the Invoke() or InvokeRepeating() method by using CancelInvoke(“MethodName”).

Waiting timer in a Coroutine

Coroutines are incredibly cool and we can use them to create well-performing timers with clean syntax. A coroutine has the ability to pause and resume itself while running in your game.

Pay attention to the using statement that includes System.Collections; we need this to be able to use coroutines.

A coroutine returns a type of IEnumerator. It is not necessary to fully understand what this means, because we’re not making use of the return type with our timer.

Inside of a coroutine, you can pause it’s execution with the yield statement. The yield can return, for example, the WaitForSeconds() method, which waits for any number of seconds passed into it before continuing execution.

Be aware, that a coroutine must include at least one yield statement. If you do not want to wait for several seconds, you can yield return null to wait until the end of the frame like any standard method does. In this example, we could omit this last step, since we we’re already yielding earlier, but just for completeness, I included it.

To start a coroutine, use StartCoroutine() and be aware, that you should pass in a method call as a parameter, as it is much faster than using a string.

Repeating timer via recursive coroutine

This heading sounds complicated, but it actually isn’t. Just look at the code:

Only one line was added to make our coroutine repeat every three seconds. In line 17 HarmPlayer() calls itself, which is known as a recursive method call.

Many times, recursive methods can get very complicated and cause hard-to-understand problems, but in our case they work nice and easy: The method waits for a period of time, then performs the print() statement and finally calls itself again, therefore repeating the timer.

You can stop a coroutine with StopCoroutine(methodName ()) or cancel all running coroutines with StopAllCoroutines().

When to use coroutines over Update()

As you might be thinking, coroutines can replace your Update() loop. I suggest to use them whenever you need time-based functionality, but you want to keep your Update() clutter free.

Coroutines are ideal for timers, moving objects via script or lerping between values.

*lerping refers to Linear Interpolation. See the official Unity tutorial for more information.

 

Please leave me a comment, if you’d like to see more practical examples of timers or if you have any more questions.

 

Photoshop – How to preview designs in grayscale

When designing anything from icons to user interfaces, it is advisable to check your design in grayscale. This helps your design in multiple ways:

  • If your design works without any color, you have a solid foundation and color can add to the functionality that is already there.
  • Color information is less reliable to work for any person viewing your design than value (how light or dark a color is). Colors appear very different on different devices and the human perception of color can vary dramatically, therefore you should never rely on only using color to distinguish design elements.

Check your design, by stripping away the color information non-destructively. This is the easiest way to do it:

Grayscale layer

Photoshop - layer to preview in grayscale.
Photoshop – layer to preview in grayscale.
  1. Create a new empty layer and fill it with black (use your keyboard shortcuts, such as CTRL + Shift + N to create a new layer and CTRL + Backspace to fill it with the background color).
  2. Set the layer’s blending mode to Saturation.
  3. This now works like an adjustment layer, which you can keep at the top and turn off and on.

There are, of course, other ways to achieve the same effect, just be aware of the additional steps.

Hue/Saturation adjustment layer

Photoshop - Hue/Saturation adjustment layer set to 0% saturation.
Photoshop – Hue/Saturation adjustment layer set to zero saturation.
  1. Create a new Hue/Saturation adjustment layer and set Saturation to 0% in the Properties panel.
  2. Set the layer’s blending more to Saturation. (Important!)
  3. Same effect as the grayscale layer mentioned above.

Personally, I think this method has drawbacks:

  • The adjustment layer icon is not as recognizable as the plain black one from the grayscale layer.
  • You have to open the Properties window and adjust the saturation manually.
  • If you forget to set the layer’s blending mode, you will get “incorrect” grayscale:
Photoshop - Hue/Saturation layer with incorrect mode for grayscale preview.
Photoshop – Hue/Saturation layer with incorrect mode for grayscale preview.

You can see that the Normal blending mode leads to a different grayscale result. In fact, this mode is not neutral at all, so do not use it to check your design.

Black & White adjustment layer

This is not really an option for previewing a “true” grayscale version of your design, as it does not provide a neutral setting. This adjustment layer is meant for changing a black and white image. If you set the layer’s blending mode to Saturation, you get the same effect as with our grayscale layer, but why have all those useless sliders from the filter then?

Grayscale color mode

Photoshop - grayscale color mode.
Photoshop – grayscale color mode.

Switching the color mode for the entire document discards color information and certain adjustment layers and Smart Objects. You might not be able to switch back to color and besides, it performs a file format conversion, which is not what we want.

Happy grayscaling to you all!

Object linking – Unity assets

This is part 3 of the examples from Object linking and embedding – Smart workflows for game developers.

Assets in Unity are linked files. They all contain a reference to their original source file, enabling automatic updates, when changes are made.

To force asset update, right click on a file and select Reimport.

Unity reimport assets to force update.
Unity reimport assets to force update.

 

It is important to note, that there is more information to an asset than just the source file:

To every imported asset, there is a hidden .meta file which contains the link and saves changes made in the Inspector.

Unity creates a .meta file for every asset.
Unity creates a .meta file for every asset.

 

This .meta file is extremely important to Unity!

If the .meta file connection is somehow lost for an asset, you might not notice an error, but Unity will no longer update the file correctly. When working in a team this can lead to confusion and broken assets.

Here’s how to avoid problems:

  • Always import assets via the Unity Project pane
  • When making changes to files, have Unity open and save your project, so that the .meta files are updated as well
  • When working with version control, make the following adjustments in Edit > Project Settings > Editor:
Unity editor settings when working with version control.
Unity editor settings when working with version control.

This will show .meta files, which is vital when working with Subversion, Git, Mercurial or any other version control system.

When Unity imports an asset it creates a GUID (Globally Unique Identifier). This number represents the link between the editor and the source file. If you are working in a team with version control and somebody imports assets into the project via the operating system’s file browser instead of Unity, it might lead to conflicts.

Unity .meta file unique identifier.
Unity .meta file unique identifier.

 

Unity tip: It is possible to edit .meta files from the outside Unity, if you know, what you’re doing. You could do a search and replace text on multiple .meta files without opening up Unity. This can be helpful if you’re trying to fix a problem that resulted from merging .meta files in your version control system.

Object linking – Microsoft Word linked files

This is part 1 of the examples from Object linking and embedding – Smart workflows for game developers.

Object Linking

A dynamic link is different from embedded content in that it contains a reference to the original source file, while any pasted object is only a static copy.

There are many file format that can be linked in a word document. For example: Photoshop files, Excel spreadsheets, Visio graphs or Illustrator vector graphics.

Here’s how to do it:

Microsoft Word - Insert object.
Microsoft Word – Insert object.

 

To create a link to one of many available data types:

  • Insert tab > Object > Create from file
  • Check Link to file

Note, that the Create New tab shows all data types, which are available to Word. Others may or may not display correctly. This list of available file formats also depends on installed third-party modules. So if you want to link an Adobe Acrobat Document, you will need to have Acrobat Pro installed, for example.

Available file formats when linking imported files.
Available file formats when linking imported files in Word.

 

Microsoft word - Link to file.
Microsoft word – Link to file.

 

Linked files are updated automatically, but in case you need to force it, right click the image and hit Update Link:

Microsoft Word - update linked file.
Microsoft Word – update linked file.

 

Note, that linked files are stored relatively to the word document. Keep this in mind:

Moving source files to a different locations, while the Word document is closed, will break the link. Word keeps a copy of the last state to ensure that you still have the last saved image to display.

While the Word document is open you can move source files and links will be updated and remain intact.

String “auto-completion”, Tags and Hash IDs

Unity Tags, Layers and Animator components are great tools to use, but they have one drawback: It is necessary to pass strings into certain MonoBehaviour methods to make them work.

Consider this short example:

There are several situations in which you can’t get around using strings as parameters for certain Unity methods. Other times it might be the most convenient and practical solution.

At this point it would be too much to talk about all the implications of using strings and how or why to avoid them. Instead, I’d like to show you a remedy for one of the many downsides of using strings in functions.

Strings as method parameters are difficult to deal with because of possible spelling-errors or tedious renaming of multiple string-instances.

The most common examples of string usage in methods are:

  • Output messages for console logging, warning messages and exceptions.
  • Accessing Animator layers and parameters
  • Identifying objects by Tag
  • Calling a method by name when using Invoke() or a Coroutine

A good solution for working with anything Animator related is to hash strings to integers and feed the Animator with ID’s instead of layer and parameter names. Int variables are much better for performance than strings. They also have the benefit of being visible in IntelliSense.

Create this script and attach it to a GameObject in the scene (Awake must be called for the StringToHash() method to create our ID’s):

I prefer to declare my hash variables as static, because then I can access them without finding a reference to them from other scripts. (A drawback is, that Unity’s debug inspector does not show static fields, so you have to set breakpoints or print to the console, if you want to debug your strings and hashes.)

If you’d like to use auto-completion on string parameters to easily remember them and prevent spelling-errors, try this:

Note, that a class which only stores variables doesn’t need to be attached to a GameObject. You can also declare multiple classes within one file.

"Auto-completion" for string values through static class.
“Auto-completion” for string values through static class.

 

Recap: Use hash ID’s for Animator layers and parameters. Store strings that will not change in a static class.

Accessing variables and communicating between scripts

One of the most common tasks in Unity is to access variables on another script or component.

Remember that a component in Unity is nothing more than a piece of code put into a class with a nice name such as Transform or BoxCollider.

Here’s an overview of different ways to read information and how to communicate between different scripts:

  1. Private variables and scope
  2. Public variables and accessors
  3. GetComponent()
  4. Static variables
  5. Messaging

Private variables and scope

At the most basic level we access information by reading private variables within a single class.

Private variables are also called member variables and are only accessible from within the class they are declared in. Their scope is limited to the containing code block, which, among others, can be a class, function or if-statement. Whenever a variable is declared in between curly braces you can only see and read from it within the same code block or nested blocks.

See code example abovehealth can be read from within the Start() method, because it was declared within the Player class which is a parent element to the Start() method. Generally, you can only read variables, which are declared at the same or a higher level than that of which your call or assignment originates, but not the other way around.

Think of a variable declaration as a “parent” and calls to that variable as “children”. The children must be contained within the parent code block.

Here is an example of a variable that is inaccessible due to scope:

The variable count is declared within a for-loop which is a code block and only exists in between the following curly braces. The print-call happens outside of that code block, it is at a higher level and therefore can’t access the variable.

A variable must be declared before it is used. When declaring  a variable on the class level, the line number on which the declaration happens is irrelevant to the compiler.

Here is an example for a variable declaration which is limited to the scope of the Start() method:

Important: A variable that is declared on a lower level than the class level (meaning: within a method), is always private and can not have any other access operator applied. Therefore, you do not need and can’t use the private keyword.

Tip: Keep in mind, that on the class level, the private accessor is implicit in C#. You may omit the keyword and the variable will still be private by default. However, many consider it best practice to always declare accessors explicitly.

Recap:

Private variables have a scope in which they are accessible; they are members of a class or other code block.

Public variables and accessors

Variables, methods and even classes are declared with a certain protection level, which limits the element’s scope in a specific way. The most common way to define scope is by the use of the private or public accessor.

Declaring a variable or method as public makes it accessible from other scripts. There is, however, a strict rule to follow when attempting to read variables from another class:

Scripts can communicate with each other via public variables if one class has a reference to the other class instance.

Here is a script example of our Player class:

Note that both the class and the variable health have the public accessor applied, which makes them visible to other scripts.

On line 5 you find a variable of the type Player. This will be used to store a reference to the Player class instance. On line 9 this variable is assigned the current player script, which lies on the same GameObject. (See the next section for more information; just know that GetComponent() returns an instance of the class we’re trying to find.)

Reminder: A class is only a template that tells the computer how to build an object. The object is created by constructing an instance from the class. (Unity does this for us automatically when we attach a MonoBehaviour script to a GameObject and press Play.) A reference tells the program where to find a specific object instance in memory.

When our Player variable holds the correct instance/object (meaning that it is not null), we can access all public variables within it by using the dot-notation:

The same works for functions:

Check out MonoDevelop Basics if you need to catch up on how to use auto-completion and other tools for convenient programming.

Remember, to access a class, method or variable from another script, they need to be declared as public. Next, the calling script needs a reference to the other class instance. Finally, you can access a member or method via dot-notation.

GetComponent()

GetComponent() is a Unity method from the MonoBehaviour class that is used to access data on other components. To fully understand how this method works, you have to wrap your head around a few different concepts.

Let’s attach our player script to the Main Camera GameObject in the Unity hierarchy and tell it to find the Camera component:

First, you declare a variable of type Camera to hold a reference to the Camera Component which you are going to find on the same GameObject. Next, you call GetComponent() in it’s generic version on the type Camera, which will return the first object of type Camera that is found.

Above is the “standard” version of GetComponent(), which might be easier to understand, because it is slightly more explicit. The method searches for a class that is called Camera by string and then passes the class as the type of Camera so that we can store it in our variable.

The as operator can be used to convert classes (they must be a reference type, so that they are able to return null!). In this case we want to convert whatever object we find that matches our search string, to a Camera object. If this works, because our camera is indeed a camera object, we basically just pass the reference.

If for whatever reason, our camera would not be of type Camera the method would return null, instead of throwing an error, which is convenient in this case, because now we can search for objects that only might exist.

Because variables which have the value null can cause Null-Reference-Exceptions, it is very common to perform a null-check before accessing such variables.

If you were to access our mainCamera variable without any null-check, Unity might throw an exception, if the variable doesn’t hold a Camera object.

Because searching by string is a relatively costly operation for computers, the generic version GetComponent<type>() is preferable. Nevertheless, GetComponent() is still a costly operation itself, so even in it’s generic version, it should be called as rarely as possible. Use it for caching variables once in Start() or Awake()!

Here’s a more complete example:

Note, that both the Player script and the Camera component are on the same GameObject in this case. (Just for testing purposes, this is not a practical example!)

In Awake() we find a reference to the camera. In Update() we adjust the camera’s field of view, but only if the reference exists.

How does GetComponent() know where to search for objects?

Until now, GetComponent() returned a component on the same GameObject, but you might be guessing that we will use it to find scripts on other GameObjects, too, so how does this work?

Consider this script for an enemy object:

In this example, we want to access multiple components on a different GameObject. Before anything can work, we will need to find a reference to the other GameObject. Once we have found an object, we can perform a GetComponent() search on it, by using the dot-notation. There are multiple ways to find references in Unity C#:

1. Assigning a reference through a public variable in the editor

When you declare a public variable in the Enemy script on the enemy GameObject, Unity will automatically create a field in the inspector, which you can use to assign a reference by visually dragging an object onto the field or selecting one from the dot-picker to the right of the field.

Unassigned reference for a public variable in the inspector
Unassigned reference for a public variable.

 

public-variable-reference_filled
Public variable with assigned reference.

Assigning references through public inspector fields is very easy to understand, but it also requires a null-check, because it is quite possible to forget to populate the inspector field. During development there are also a few situations, which might break such a manually established connection, especially when working with Prefabs in Unity. Still, it’s a very design-friendly solution to quickly hook up things.

Best usage: Use public inspector fields, when you want to give a designer the control over which reference is assigned. For example a Camera-Follow script that takes a public variable Target and follows any object that is assigned through the inspector.

Public inspector variable with unassigned Transform.
Public inspector variable with unassigned Transform.

Note, that inspector fields show us which type a variable/field expects. When you drag a GameObject onto a field that says “None (Transform)” the editor will automatically assign the Transform component of the object.

2. GameObject.Find()

This Unity method returns the first active GameObject that matches a given string parameter. The search is performed on the entire scene.

Recommendation: Be cautious when using this method, because it is slow! If you must use it, then only call it once in Awake() or Start().

Active GameObject in inspector.
Active GameObject in inspector.

Be aware of the fact, that GameObject.Find() only returns active objects. Also, if you rename your objects during development, you will have to adjust your scripts as well, which might become tedious, since Game Designers like to rename things to make them look pretty in the hierarchy…

3. GameObject.FindWithTag()

A better alternative is to search for objects by Unity Tag. First, assign a tag to your GameObject via the Inspector:

Inspector Tag on GameObject
Inspector Tag on GameObject.
Add Tag to GameObject in Inspector
Add Tag to GameObject in Inspector.

Add Tag… will take you straight to Unity’s Tags and Layers editor, which you can also find at Edit > Project Settings > Tags and Layers. Here you can create a custom tag, which will then appear next to the default one’s in the Tag list. Once our player is tagged with the Player tag, we can easily find a reference by using GameObject.FindWithTag():

GameObject.FindWithTag() is not the fastest solution, but a practical one.

You can use this method for individual objects like a player or a game manager. You should only call it once and cache the result in a variable. Performing the search on a hundred objects tagged Enemy might be slow, so reconsider your options when dealing with many entities.

Would you like to use auto-completion for your tags? Here’s another trick when working with strings as parameters: Strings, Tags and Layers

4. Transform.GetChild()

If your GameObjects have a fixed relationship in the hierarchy, you can find them by index with Transform.GetChild().

Note, that the Unity hierarchy is built with Transforms. So when traversing the hierarchy to find another object, you are going to use the Transform class.

Hierarchy Transforms
Hierarchy Transforms

As you can tell from the inspector, all elements in the hierarchy include a Transform component, which can be accessed by an index starting at zero. When trying to find the first child object in a parent-child relationship, we search for index 0.

Now that you have found a reference to a GameObject and stored it in a local variable, you can access it via the dot-notation and use GetComponent() to pick a specific component.

So let’s put it all together:

Here’s another trick, how you can visually check if a private variable has been populated or not.

Recap:

  1. Declare variables for components you wish to store in your class (line 5 – 6).
  2. Find a reference to the GameObject on which those components live (line 10). You also declare playerGO locally because you won’t be needing it any longer, once the variables for playerScript and playerTransform are assigned.
  3. Don’t forget a null-check to prevent errors!
  4. Assign the final variables by using GetComponent().

It is true, that there’s a plethora of ways to find references and store them. Remember, it is ok to just go ahead with the first solution, that comes to mind and then improve it later!

Generally, try to get to your data in as few steps as possible. For example, if you’re looking for the weapon’s Transform, consider traversing the hierarchy from the player to the child objects, instead of looking for a GameObject first and then doing a GetComponent() to find the Transform. Save on method calls and dot-notation operations!

Addendum:  We’ve learned that GetComponent() performs a search for a component type/class on a GameObject by using the dot-notation.

By now, you should know exactly what’s going on when you see the above example. We’re looking for the playerPosition by performing a GetComponent() on our player reference and then going one level deeper into the Transform position.

If you’re on top of things, you might wonder:  “Why use GetComponent() in this case, when there clearly is an easier way…”

True, you might as well do this:

Let’s clear things up: transform is a Unity property that does a GetComponent() call with <Transform>. Read more here.

We start to get a grip of the idea, that GetComponent() is always called on some kind of object via the dot-notation, but why are we allowed to do this:

GetComponent() always needs to know on which object to perform a search and here it seems as if this information was missing. However, the above line 9 is basically a shorthand for:

MonoBehaviour offers us another built-in property called gameObject, which will return the GameObject to which our script is attached. Therefore, gameObject and transform are also calls to the GetComponent() function. Read this if you’re interested in knowing why you shouldn’t use those properties in your Update() loop.

Static variables

Now comes a part, in which the humble beginner might think: “well this is the easiest method of accessing variables across scripts, why not use this one first place?” To which I will reply: “static variables are great, but there’s much to learn before one can safely use them!”

A static variable lives on a level with the class template, not with the individual instances of a class. It is a single entity which is shared by all class instances.

We’ve learned, that Unity creates instances of our classes when we attach them to GameObjects and start the game. So if we create multiple enemies, all of which have an Enemy script attached, which stores health, each enemy has their own instance of the health variable. Try it out!

  1. Create a GameObject called Enemy.
  2. Attach the Enemy script to it.
  3. Duplicate the enemy a few times.
  4. Assign each enemy a different health through the public field in the inspector.
  5. Press play and watch the console output different health values for each enemy.

Nothing new here, so let’s add in a static variable:

When you look at the inspector, you will find that Unity doesn’t allow us to set static variables through the editor. (It would be rather confusing, if it were possible, anyway…)

Instead, we increment the count variable whenever an enemy script is started by Unity. Since every enemy is created only once per session, our static count will tell us how many enemies we’ve created.

In short: We’ve created multiple instances of the Enemy class by duplicating the GameObjects in the Editor. Every instance has their own set of private and public variables, but all of them share a single static variable called count.

To avoid confusion: the static keyword is not an accessor, it is meant to create a single variable that lives among your class object.

Let’s make it even clearer and create a new testing script on our Main Camera:

Active camera with Test script.
Active camera with Test script.

Then deactivate our enemies in the inspector. Turning off GameObjects in Unity sets them inactive. On a component level this is called enabled or disabled.

Enemies inactive in hierarchy.
Enemies inactive in hierarchy.

Press play, watch the console and start to activate one enemy after the other by clicking the checkboxes for each GameObject. You will see how the count variable is incremented with every new enemy that comes alive.

The count variable increments.
The count variable increments.

Now, while the Unity player is running, select your enemies and delete them from the hierarchy. The count variable will still be printed to the console, because it still exists, although all of the enemy class instances were deleted.  If you’re window doesn’t show the print output in four compact statements, hit Collapse at the top row of the console tab.

Further reading on counting enemies: If you actually want to use the count variable for something, you probably want it to tell us the amount of enemies that are currently alive. A typical way of doing this:

The OnEnable() and OnDisable() methods are built-in MonoBehaviours just like Start(). They get called whenever the script is turned on or off. This is true, when enabling the script itself, as well as when deactivating the GameObject on which the script resides.

Messaging

I’ve included messaging in this article, because it’s one of the main ways to communicate elegantly between script and you should consider using it in your own projects as soon as you’ve mastered the previous sections.

Because sending messages in Unity is worth it’s own topic, please continue reading here.