Summary

Control flow determines which code runs and how many times it runs. In C#, if/else statements branch on conditions, for loops repeat a known number of times, and while loops repeat until a condition changes. Almost every game system, including collecting pickups, tracking health and processing waves of enemies, is built from these three constructs working together.


Key ideas

Comparison operators:

OperatorMeaning
==Equal to
!=Not equal to
<Less than
<=Less than or equal to
>Greater than
>=Greater than or equal to

Logical operators:

OperatorMeaning
&&AND: both conditions must be true
||OR: at least one condition must be true
!NOT: inverts a boolean value

for loop: Use when the number of iterations is known in advance. This usually means iterating over an array or repeating a fixed number of times. The loop variable i is conventional but not required.

while loop: Use when the number of iterations is not known in advance. This means looping until a condition becomes false, such as health reaching zero or a target score being reached.

foreach loop: Use when you want to visit every item in a collection and you do not need the index. It is often the clearest way to loop through a List<T> or array.

Ternary operator: A compact inline conditional that evaluates to one of two values. Useful for short label or flag assignments.


In practice

if / else if / else:

int health = 20;
int score = 150;
 
if (health <= 0)
{
    Debug.Log("Game over!");
}
else if (health < 25)
{
    Debug.Log("Low health warning!");
}
else
{
    Debug.Log("Health: " + health);
}
 
// Logical operators
if (health <= 0 && lives == 0)
{
    Debug.Log("No lives remaining.");
}

for loop, iterating over an array:

int[] coinValues = { 10, 25, 10, 50, 15 };
int total = 0;
 
for (int i = 0; i < coinValues.Length; i++)
{
    total += coinValues[i];
}
 
Debug.Log("Total coins: " + total);

foreach loop, iterating without an index:

string[] collectedItems = { "Key", "Potion", "Map" };
 
foreach (string item in collectedItems)
{
    Debug.Log("Collected: " + item);
}

Use foreach when you just want each item. Use for when you need i for the position, want to skip around by index, or need to replace elements in place.

while loop, condition-based repetition:

int health = 100;
int damagePerTurn = 15;
int turn = 0;
 
while (health > 0)
{
    health -= damagePerTurn;
    if (health < 0) health = 0;  // clamp
    turn++;
    Debug.Log("Turn " + turn + ": health " + health);
}
 
Debug.Log("Defeated after " + turn + " turns.");

Should I use if or while to check if a player is alive?

Use if for a normal gameplay check:

if (playerHealth > 0)
{
    Debug.Log("Player is alive.");
}

That asks one question once, at this point in the code.

Use while only if you genuinely want to keep looping until the condition changes:

while (playerHealth > 0)
{
    playerHealth -= poisonDamagePerTick;
}

That is much rarer in everyday Unity gameplay code. Most of the time, checking whether a player is alive is an if, not a while.

Ternary operator:

// condition ? value-if-true : value-if-false
string status = (health <= 20) ? " [LOW HEALTH]" : "";
Debug.Log("Enemy HP: " + health + status);

Loops and conditions combined, the core game logic pattern:

int[] enemyHealth = { 0, 45, 0, 80, 12 };
int aliveCount = 0;
 
for (int i = 0; i < enemyHealth.Length; i++)
{
    if (enemyHealth[i] > 0)
    {
        aliveCount++;
        if (enemyHealth[i] <= 20)
            Debug.Log("Enemy " + i + " critically low: " + enemyHealth[i] + " HP");
    }
}
 
Debug.Log(aliveCount + " enemies remaining.");

Variables declared inside a loop body:

for (int i = 0; i < enemyHealth.Length; i++)
{
    int currentHealth = enemyHealth[i];
    Debug.Log(currentHealth);
}

currentHealth is created fresh each iteration because it is declared inside the loop body. You can think of it as a temporary variable that only exists for that single pass through the loop.

By contrast, the loop counter i keeps changing value across iterations because it is declared in the for (...) header and then updated by the loop itself.


Gotchas

  • A while loop with a condition that never becomes false will freeze Unity. Always ensure something inside the loop modifies the condition variable.
  • Clamping after arithmetic (if (health < 0) health = 0;) is a recurring pattern. Forgetting it allows values to go negative, which can cause unexpected behaviour in UI and game logic.
  • The for loop counter variable i is zero-based. When printing “Enemy 1, Enemy 2…” for human display, print i + 1 rather than i.
  • A foreach loop gives you each item in turn, but not the index. If you need both the item and its position, use a for loop instead.

Practice

Trace this code by hand before running it:

int[] enemyHealth = { 0, 10, 35, 5 };
int alive = 0;
int weak = 0;
 
for (int i = 0; i < enemyHealth.Length; i++)
{
    if (enemyHealth[i] > 0)
    {
        alive++;
 
        if (enemyHealth[i] <= 10)
        {
            weak++;
            Debug.Log("Weak enemy at index " + i);
        }
    }
}
 
Debug.Log("Alive: " + alive);
Debug.Log("Weak: " + weak);

Then change the rule so that enemies with exactly 0 health print "Defeated enemy at index X". Keep the alive and weak counts correct.

Self-test

  1. When should you use if instead of while?
  2. When should you use for instead of foreach?
  3. What is the final value of alive in the practice code?
  4. What is the final value of weak in the practice code?
  5. Why is currentHealth declared inside the loop body in the earlier example?

Answers

  1. Use if when you need to make one decision at the current point in the code. Use while only when the code must repeat until a condition changes.
  2. Use for when you need the index, need to replace items by position, or need more control over the loop. Use foreach when you only need each item.
  3. alive becomes 3 because three enemies have health greater than 0.
  4. weak becomes 2 because the enemies at index 1 and index 3 have health greater than 0 and less than or equal to 10.
  5. currentHealth is declared inside the loop body because it is temporary. A fresh value is read for each pass through the loop.