Summary

A variable is a named container that holds a value the game needs to remember. C# is a statically typed language — every variable must declare its type, and that type cannot change. The four types used throughout Unity game scripting are int, float, bool, and string. Choosing the right type matters: speed can be 2.5 units, but not 2.5 lives.


Key ideas

Core types:

TypeStoresGame examples
intWhole numbersscore, lives, level, health
floatDecimal numbersmoveSpeed, jumpForce, timer
booltrue or falseisAlive, isGameOver, isGrounded
stringTextplayerName, levelName

const: A value that is fixed at compile time and can never be modified. Use it for values that must not change, such as maximum health or a fixed damage multiplier.

Access modifiers in Unity:

  • public — accessible from other scripts; also appears in the Inspector.
  • private — accessible only within this script; hidden from the Inspector by default.
  • [SerializeField] — makes a private field visible in the Inspector without making it accessible to other scripts. Preferred over public when Inspector access is needed but external access is not.

[Header("...")]: An Inspector attribute that adds a bold label above a group of fields. Used to organise related variables visually in the Inspector.

Arrays: An ordered collection of values of the same type. Size is fixed at initialisation. Elements are accessed by their zero-based index; the Length property returns the number of elements.

Fields vs local variables: A field is declared at class level, outside any method. It belongs to the object and remembers its value between calls to Start, Update and other methods. A local variable is declared inside a method or block. It exists only while that method or block is running.


In practice

// Basic type declarations
int score = 0;
int lives = 3;
float moveSpeed = 5.5f;   // float literals require the 'f' suffix
bool isAlive = true;
string playerName = "Hero";
 
// const — value cannot be changed anywhere
private const int MaxHealth = 100;
// Inspector-visible fields using public and [SerializeField]
[Header("Player State")]
public int health = 100;          // public — visible in Inspector, accessible to other scripts
 
[SerializeField]
private float jumpForce = 8f;     // private — visible in Inspector, not accessible externally
// Arrays
int[] coinValues = { 10, 25, 10, 50, 15 };   // initialise with values
string[] levelNames = new string[4];          // initialise empty with size
 
// Access by index (zero-based)
int first = coinValues[0];    // 10
int last  = coinValues[4];    // 15
 
// Length property
int count = coinValues.Length;  // 5

Compound assignment operators:

score += 10;   // same as: score = score + 10
score -= 5;    // same as: score = score - 5
health *= 2;   // same as: health = health * 2

Tracing state through a small game rule:

[SerializeField] private int health = 100;  // field: remembered by the object
 
private void TakeDamage(int amount)
{
    int oldHealth = health;     // local variable: exists only during this call
    health -= amount;           // field changes and stays changed
 
    Debug.Log($"Health changed from {oldHealth} to {health}");
}

Read this code in order:

  1. health starts as object state and can be seen in the Inspector.
  2. amount is supplied by whoever calls TakeDamage.
  3. oldHealth temporarily remembers the previous value so the log message can explain the change.
  4. health -= amount changes the field, so the new value remains after the method ends.

Gotchas

  • float literals must have an f suffix: 5.5f not 5.5. Without it, C# treats the value as a double and the assignment will fail to compile.
  • Array indices start at zero. An array of 5 elements has indices 0–4; accessing index 5 throws an IndexOutOfRangeException.
  • Prefer [SerializeField] private over public when you only need Inspector access. Making a field public for Inspector convenience exposes it to unintended external mutation.
  • const fields are implicitly static — they belong to the type, not to an instance. They cannot be modified at runtime and cannot be exposed to the Inspector.
  • A local variable declared inside Update resets every frame. If a timer, score or state flag needs to remember its value, declare it as a field.