What is Control Flow?
Control flow is how your code decides what to do, when to do it, and how many times to do it. It’s the logic engine of your game–controlling gameplay decisions, movement, AI behavior, win/loss conditions and more.
Why It Matters in Unity
In a game:
- Should the door open?
- Should the enemy chase you?
- Should a player respawn or die?
- Should coins be added or ignored?
All of these are controlled using control flow statements.
Types of Control Flow Statements
if / else if / else
These run code only if a condition is true.
if (health <= 0)
{
Debug.Log("You died.");
}
else if (health < 50)
{
Debug.Log("Low health!");
}
else
{
Debug.Log("You’re healthy!");
}
Example in Unity:
if (Input.GetKeyDown(KeyCode.Space))
{
Jump();
}
Switch Statement
An alternative to long chains of if/else. Great for handling multiple fixed cases.
string state = "Walking";
switch (state)
{
case "Idle":
PlayIdle();
break;
case "Walking":
PlayWalk();
break;
case "Running":
PlayRun();
break;
default:
Debug.Log("Unknown state");
break;
}
When to use it:
- Player modes
- Item types
- Menu selections
for Loops
Runs a block of code a set number of times
for (int i = 0; i < 3; i++)
{
Debug.Log("Loop count: " + i);
}
Examples in Unity
for (int i = 0; i < enemies.Count; i++)
{
enemies[i].TakeDamage(10);
}Loop through all enemies and apply 10 damage to each.
foreach Loops
Used to go through every item in a collection.
foreach (string name in playerNames)
{
Debug.Log("Player: " + name);
}
Examples in Unity:
foreach (GameObject enemy in GameObject.FindGameObjectsWithTag("Enemy"))
{
enemy.SetActive(false);
}Finds every gameObject in scene with tag “Enemy” and deactivates them.
while Loops
Repeats code as long as a condition is true.
int i = 0;
while (i < 5)
{
Debug.Log(i);
i++;
}
Example in Unity
while (playerInZone)
{
HealPlayer();
yield return new WaitForSeconds(1f);
}Tip: Use while inside Coroutines to avoid freezing the game.
do while Loops
Like while loops but runs at least once before checking the condition. Perfect when you want “at least one guaranteed action”, even if the condition might not be true later. In a normal while, it might skip entirely if the condition is false right away.
int coins = 0;
do
{
Debug.Log("Still broke. . .");
coins++;
}
while (coins < 1);
Examples in Unity
Loot Chest with guaranteed Rare Item
private string[] items = {"Common Sword",
"Common Shield", "Rare Gem", "Common Potion" };
private string selectedItem;
void Start()
{
OpenChest();
}
void OpenChest()
{
do
{
int randomIndex = Random.Range(0, items.Length);
selectedItem = items[randomInex];
Debug.Log("Rolled: " + selectedItem);
}
while (!selectedItem.StartsWith("Rare"));
Debug.Log("You obtained a rare item: " +
selectedItem + "!");
}the do-while loop rolls an item from the chest. It keeps rolling until it gets an item that starts with “Rare”. It logs each roll so you can see how many tries it took.
do means run this code once no matter what.
while (condition) checks if it should repeat.
Gun Reloading Example
The player reloads bullets one at a time until the clip is full (would be great for revolvers and pump-action shotguns.
public int roundsInCylinder = 3;
public int cylinderSize = 6;
void Start()
{
Reload();
}
void Reload()
{
do
{
roundsInCylinder++
Debug.Log("Reloading... Current ammo: " + roundsInCylinder);
}
while (roundsInCylinder < cylinderSize);
Debug.Log("Reload Complete!");
}Starts with 3 rounds.
Reloads one round at a time.
Stops once rounds = cylinder size (6).
Guaranteed at least one reload action even if cylinder is already almost full.
break and continue
break = exit the loop
continue = skip this loop iteration
for (int i = 0; i < 10; i++)
{
if (i == 3) continue; // Skip 3
if (i == 7) break; // Stop at 7
Debug.Log(i);
}
Combining Control Flow
You can mix control flow for powerful logic
break and continue are huge for making loops more responsive and natural.
foreach (Enemy enemy in enemies)
{
if (enemy.health <= 0)
{
enemy.Die();
continue;
}
if (playerInRange)
{
enemy.Chase(player);
}
}
Spawning enemies with random boss chance
Uses: do-while, if, and break
using UnityEngine;
public class EnemySpawner : MonoBehaviour
{
public GameObject enemyPrefab;
public GameObject bossPrefab;
public int maxEnemies = 10;
void Start()
{
int spawned = 0;
do
{
// 10% chance to spawn a boss
if (Random.value < 0.1f)
{
Instantiate(bossPrefab, RandomPosition(), Quaternion.identity);
Debug.Log("Boss spawned!");
break; // End the loop early after spawning boss
}
else
{
Instantiate(enemyPrefab, RandomPosition(), Quaternion.identity);
Debug.Log("Enemy spawned: " + spawned);
}
spawned++;
}
while (spawned < maxEnemies);
Debug.Log("Spawning complete!");
}
Vector3 RandomPosition()
{
return new Vector3(Random.Range(-10f, 10f), 0, Random.Range(-10f, 10f));
}
}do-while keeps spawning enemies
if creates a 10 percent chance to spawn a boss
break exits loop early if boss is spawned
Damage Player until health runs out
using UnityEngine;
public class DamagePlayer : MonoBehaviour
{
public int playerHealth = 100;
void Start()
{
while (playerHealth > 0)
{
int damage = Random.Range(5, 20);
if (damage < 10)
{
Debug.Log("Weak hit, ignoring...");
continue; // Skip weak hits
}
playerHealth -= damage;
Debug.Log("Player took " + damage + " damage! Health: " + playerHealth);
if (playerHealth <= 0)
{
Debug.Log("Player defeated!");
break;
}
}
}
}while loop runs while the player is alive
if filters weak hits (attacks that would deal less than 10 damage)
continue skips weak damage
break ends loop if player dies
Common Mistakes and Troubleshooting
Using = instead of ==
if (health = 0) // WRONG: assigns 0 to healthfix:
if (health == 0) // Correct: checks if health is 0
Forgetting Braces {}
if (isDead)
Debug.Log("Game Over");
Restart(); // ALWAYS runs — not part of `if`fix:
if (isDead)
{
Debug.Log("Game Over");
Restart();
}
Infinite while loops in Update()
// This will FREEZE the game!
while (true)
{
Debug.Log("Looping forever...");
}fix: Only use while inside coroutines with yield, or use if and timers in Update.
Incorrect Loop Conditions
for (int i = 10; i < 5; i++) // This never runs!fix: Ensure your loop makes logical sense. This loop starts at 10 and runs only while i < 5, so it never starts.
Modifying Collections While Looping
foreach (var enemy in enemies)
{
enemies.Remove(enemy); // Error!
}fix: Use a for loop backward or store items to remove:
for (int i = enemies.Count - 1; i >= 0; i--)
{
if (enemies[i].health <= 0)
enemies.RemoveAt(i);
}
Not using break in switch
switch (weapon)
{
case "Pistol":
EquipPistol();
case "Shotgun":
EquipShotgun(); // Runs this too!
}fix: Always use break; to stop after the matching case:
case "Pistol":
EquipPistol();
break;
Quick Reference
IF Statements
if (condition)
{
// do this
}
else if (anotherCondition)
{
// do this instead
}
else
{
// fallback
}SWITCH
switch (value)
{
case 0: DoSomething(); break;
case 1: DoAnotherThing(); break;
default: HandleUnknown(); break;
}FOR Loop
for (int i = 0; i < 5; i++)
{
Debug.Log(i);
}FOREACH Loop
foreach (var item in list)
{
UseItem(item);
}WHILE Loop
while (condition)
{
DoSomething();
}DO…WHILE Loop
do
{
TrySomething();
}
while (!Success());BREAK / CONTINUE
for (int i = 0; i < 10; i++)
{
if (i == 5) continue; // Skip 5
if (i == 8) break; // Exit loop
}TERNARY (Short If/Else)
string status = (health > 0) ? "Alive" : "Dead";