Variables

A variable is a value stored in memory (RAM) that can be used by your application, for example:

// type name = value;
int x = 0;

This is the declaration of a variable:

  • The variable is an int (see Types for more information).
  • The name of the variable is x.
  • The value of the variable is being set to 0.

We could then use x = 3; to change the value to 3 or if (x == 3) to execute some code only if x is 3. See Methods for more information.

The C# Documentation has a more detailed explanation of Types, variables, and values.

Var

C# is a Strongly Typed language, meaning that every variable must have a specific Type such as bool or int. For example:

  • You can write int x = 0; but bool x = 0; will give a Compiler Error because 0 is not a bool.
  • Similarly, you can write bool x = true; but not bool x = 0;.

The var keyword simply tells the compiler to automatically figure out what type to use based on whatever you are assigning to it. For example, the columns of the following table each contain two variations of the exact same thing:

int bool Rigidbody
int x = 0; bool x = true; Rigidbody rigidbody = GetComponent<Rigidbody>()
var x = 0; var x = true; var rigidbody = GetComponent<Rigidbody>()

Other than the obvious benefit of saving a bit of typing for long names, the var keyword will also automatically change its type if you change what you are assigning to it. This means that in the Rigidbody example above, if you want to change your game to use Unity's 2D physics system and are using var, you would only need to change Rigidbody to Rigidbody2D in one place instead of two.

Arrays

An array is a data structure, which can store a number of variables of the same Type. Arrays in C# are the main use for square brackets [ ]. For example:

var numbers = new int[3];
numbers[0] = 0;// Set the first element to 0. Unnecessary because the default value is 0.
numbers[1] = 2;// Set the second element to 2.
numbers[2] = 6;// Set the third element to 6.
  • The variable is an array of ints.
  • The name of the variable is numbers.
  • The array contains 3 values which are all currently 0 (because that is the default value for ints).
  • Trying to access numbers[3] would cause an Exception because the array does not have a fourth value.
  • numbers.Length will tell you the size of the array.
  • As noted in the Types section, arrays are reference types which will be Garbage Collected.

Lists

Once an array has been created, its length cannot be changed. If you do not know how many elements you will need in an array, you may want to use a List instead. List is a class that manages an array internally and will re-allocate a larger one if you try to add more elements than its current capacity. For example:

var numbers = new List<int>();
numbers.Add(0);// Add 0 to the list (as the first element).
numbers.Add(2);// Add 2 to the list (as the second element).
numbers.Add(6);// Add 6 to the list (as the third element).
  • The List class is inside the System.Collections.Generic Namespace, meaning you either need to have using System.Collections.Generic; at the top of the script or write System.Collections.Generic.List every time you use it.
  • You can access the elements of the List using numbers[index] just like an array.
  • numbers.Count will tell you the number of elements currently in the list.
  • numbers.Capacity will tell you the number of elements you can add before the internal array needs to be re-allocated (which will cause the old smaller array to be Garbage Collected).

Fields

Local Variables Fields
Variables declared inside a Method are called local variables. They are only accessible within that method and will not remember their values if the method ends and is called again. Variables declared outside a Method are called Fields. They are accessible from anywhere in the declaring Type and possibly other types depending on their Access Modifier.
public class Example : MonoBehaviour
{
    private void Update()
    {
        int number = 0;

        if (number > 0) { ... }

        number = 6;
    }
}
public class Example : MonoBehaviour
{
    private int _Number = 0;

    private void Update()
    {
        if (_Number > 0) { ... }

        _Number = 6;
    }
}
Local variables only exist within their method and are forgotten when the method ends so the if statement in the above code will never be true because the number is always 0 at the start of the method. Fields retain their value for as long as the object exists so the first time the method executes the if statement will be false, but then the _Number gets set to 6 so the if will be true each time the method executes after that.

Since local variables and fields serve very different purposes, most coding standards (including my Coding Standard) use different naming conventions in order to make it obvious which kind of variable is being used at a glance.

The var keyword cannot be used for fields. You must always explicitly specify the type you want to use.

Field Initializers

Local variables must be explicitly given a value before they can be used, but fields are automatically given a Default Value depending on their Type (null for reference types, 0 for numbers, false for bools). Assigning a different value as part of the field declaration is known as a "field initializer":

public int health;// No initializer. Default value is 0.
public int health = 100;// Field initializer sets it to 100.

Field initializers are the first thing to be executed when a new object is created, before even the Constructor is called.

Serialized Fields

Serialization is the process of converting an object into a stream of raw bytes, generally so that it can be saved in a file or sent over a network. Unity has an inbuilt serialization system which allows it to display the values of your scripts in the Inspector so you can edit them and then save those values as part of the Scene. For Unity to serialize a field, it must either be public or have a [SerializeField] attribute (as well as several other restrictions described in the Serialization Rules section):

Code Inspector
public class Example : MonoBehaviour
{
    public int myPublicField;

    [SerializeField]
    private int _MyPrivateField;
}

It is generally recommended that you use the [SerializeField] attribute because a public field could be modified by any other script when you are not expecting it, which can cause bugs that are hard to track down. Of course, if you do want to let other scripts access the field freely then you can make it public or use a Property to wrap it. See Access Modifiers for an explanation of the public and private keywords.

If you want your own class or struct to be usable as a serialized field, you need to give it a System.Serializable attribute as demonstrated in the Root Motion example.

Default Values

You can give a serialized field a default value like so: [SerializeField] private int _SomeValue = 6;

  • When you first add the script to an object, it will initialize the field with that value.
  • But after that, the value will be serialized and it will always use the serialized value, even if you change the default to something else. The new default will only affect newly added instances of your script.

Usage Warnings

There are many Compiler Warnings in C# which are often very useful indicators that you are doing something not quite right, however they are just general recommendations and they are sometimes wrong. In particular, it is common to get the following warning when using serialized fields in Unity:

CS0649: Field is never assigned to, and will always have its default value.

Most serialized fields are given a value in the Inspector which is saved so that at runtime Unity will de-serialize the saved value and assign it to the field, but then after that the value of the field is used in various calculations and operations but is not actually changed. This means that nothing in the script actually sets the value of that field (since it is set by Unity) and since [SerializeField] is a Unity attribute which the compiler does not know about, it thinks that the field is never given a value so it gives you that warning which is obviously not very helpful in that case.

Rather than ignoring it and ending up with lots of useless warnings in the Console window all the time, you can put #pragma warning disable CS0649 at the top of your script to disable that warning within that script.