Loops: do something again and again
A loop repeats work for you. Without one, printing the numbers 1 to 100 means typing print a hundred times. With a loop you write that line once and tell Lua to run it a hundred times. That is the whole point: stop copying and pasting the same line, and let the computer do the repeating. By the end of this lesson you will write two kinds of loop and understand the single mistake that can freeze a real FiveM server.
Watch
What a loop is
Most code runs once, top to bottom, like reading a page. A loop breaks that rule. It runs a chosen block of code again and again before moving on. You decide how many times, or you decide a condition that says when to stop.
Think of a chorus in a song. The verses play once each, but the chorus repeats. A loop is the chorus of your program: one block of lines, sung over and over, until you say enough.
Vocabulary
- loop
- A piece of code that runs the same block more than once instead of just once.
- iteration
- One single pass through the loop's block. If a loop runs five times, that is five iterations.
- for loop
- A loop that counts. You give it a start number and a stop number, and it runs once for each number along the way.
- while loop
- A loop that repeats as long as a condition stays true, and stops the moment that condition becomes false.
The numeric for loop
The most common loop in FiveM code is the numeric for loop. It counts from a start number to a stop number and runs the block once for each value.
for i = 1, 5 do
print(i)
endRead it left to right. for opens the loop. i = 1 sets a counter called i and starts it at 1. The 5 is where it stops. do marks the start of the block, and end marks the finish. On each pass, i holds the current number, then Lua bumps it up by one and runs the block again. When i would pass 5, the loop ends.
The counter i is just a normal variable. The name i is a habit borrowed from math, short for "index". You could call it count or n and it would work the same. Inside the block, i is a real value you can use: print it, add to it, compare it. Each iteration, it is one bigger than the last.
There is an optional third number, called the step. It controls how much the counter jumps each time. Leave it out and the step is 1.
for i = 0, 10, 2 do
print(i)
endThat counts 0, 2, 4, 6, 8, 10, stepping by 2. A negative step counts downward:
for i = 5, 1, -1 do
print(i)
endThat counts 5, 4, 3, 2, 1. So the shape is for counter = start, stop, step do, and the step is the only part you are allowed to drop.
See it run
No server needed. Edit the Lua below and press RUN to execute it in your browser on real Lua 5.4. Change the start and stop numbers and watch the output change.
Press RUN to execute.
The .. joins two strings end to end, so "Count: " .. i glues the word Count: onto whatever number i holds right now. You should see this:
Five lines, one per iteration. You wrote one print and got five outputs. That is the loop earning its keep.
The while loop
A for loop is for when you know the count up front: one to five, ten down to one. Sometimes you do not know the count. You only know a condition that should keep the loop going. That is the while loop.
while condition do
-- code that runs while condition is true
endwhile checks the condition first. If it is true, it runs the block, then checks again. The moment the condition is false, it stops and the program moves on. The key responsibility is yours: something inside the block has to eventually make that condition false, or the loop never stops.
Here is a counter that climbs to 3 and then quits. Press RUN.
Press RUN to execute.
Trace it. count starts at 1. The condition count <= 3 is true, so it prints Tick 1, then count = count + 1 makes count 2. True again, prints Tick 2, count becomes 3. Still true, prints Tick 3, count becomes 4. Now 4 <= 3 is false, so the loop stops and Done prints. The line count = count + 1 is what makes the condition eventually fail. Delete it and the loop would run forever.
Lua has no ++ or +=. To add one to a number you write the variable out: count = count + 1. That reads as "set count to its current value plus one". This single line is the engine of most while loops, so get comfortable with its shape.
You can also stop a loop early from the inside with break. It quits the loop immediately, no matter what the condition says.
local count = 1
while true do
print(count)
if count >= 3 then
break
end
count = count + 1
endHere the condition is literally true, which would normally never stop. The break inside the if is the real exit. When count reaches 3, break fires and the loop ends. A while true loop is only safe when something inside it is guaranteed to break or, on a server, to pause.
The one rule that matters later: never loop forever without a pause
This is the most important idea in the lesson, so read it twice. A loop with no exit, like while true do with no break and no pause, will run forever. The computer does nothing else while a loop is running. It is too busy spinning through the block to draw the screen, answer the network, or react to anything. So an endless loop with no pause freezes the whole program.
In the browser sandbox, an endless loop just hangs the tab. Annoying, but you can close it. On a real FiveM server it is far worse: an endless loop in your script freezes the entire server for every player connected to it.
The fix on a real server is to give the loop a short pause each time around so the server can breathe and do its other work between passes. You do not need to write this yet, but here is what it looks like, so it is not a surprise later:
Citizen.CreateThread(function()
while true do
-- do a little work
Citizen.Wait(1000) -- pause for 1000 ms, then loop again
end
end)The Citizen.Wait(1000) line tells the server "rest for one second, then come back to me". That single pause is the difference between a smooth server and a frozen one. You will learn exactly how this works in Track B. For now, just lock in the rule.
A quick tool you will need: the remainder
Before the exercise, one small operator. The % sign gives you the remainder left over after a division. 10 % 2 is 0, because 10 splits into 2 with nothing left over. 7 % 2 is 1, because 7 splits into two threes with 1 left over. The handy trick: a number is even exactly when dividing it by 2 leaves nothing behind, so n % 2 == 0 is true for even numbers and false for odd ones. You will use that check in a moment.
Common beginner mistakes
| Symptom | Fix |
|---|---|
The page or program freezes / hangs | An endless loop with no exit. Give a while loop a condition that becomes false (change a counter inside the block), or add a break, or on a real server a Citizen.Wait. A loop that never ends locks up everything. |
off-by-one: the loop runs one too few or too many times | for i = 1, n runs n times and includes n itself. If you wanted 0 to n that is n + 1 iterations. Double check your start and stop values against how many passes you actually want. |
the while loop body never runs | The condition was already false on the first check. A while loop tests before it runs, so if count starts at 10 and the condition is count < 5, the block never executes once. |
How many times does for i = 1, 3 do run?
Three times. The counter i takes the values 1, 2, and 3, one pass each, and the stop number 3 is included. A numeric for from 1 to n always runs n times.
Try it yourself
What you can do now
- Explain what a loop is and why it beats copy and paste: one block, run many times.
- Write a numeric for loop with a start, a stop, and an optional step, and know the stop value is included.
- Write a while loop that repeats on a condition, and make sure something inside it eventually makes the condition false.
- Use break to leave a loop early, and read why a while true loop needs a break or a pause.
- State the one rule: never loop forever without an exit or a pause, because an endless loop freezes everything.
You can now make code repeat, and you know the trap that turns a useful loop into a frozen server. Next you will learn to package code so you can name it once and reuse it anywhere, instead of rewriting the same lines in every file. That is the next lesson, "Functions: reuse your code".