Learn game programming
Debugging basics for game developers
A broken build is not a crisis, it is a checklist. Read the error, find the owning line, prove the fix — the same method every time.
Debugging is the job, not the interruption
Beginners tend to treat a bug as evidence that something went wrong with them. It is worth replacing that framing early, because it is both wrong and expensive: professional developers spend a large share of their time reading broken things and working out why. The difference between a beginner and a professional here is not how often they hit bugs. It is that the professional has a method and does not panic.
The method below works on every language and engine, because it does not depend on any of them. It depends on being willing to find out what is actually true instead of guessing.
Step 1 — Read the error properly
Error messages look hostile and are mostly generous. A typical one tells you three things: what went wrong, which file it happened in, and which line. Beginners routinely skip straight to the code and never read the sentence — which is a bit like ignoring a diagnosis because the words are long.
Read it out loud if it helps. undefined is not a function means you tried to call something that does not exist — usually a typo or a name that is not in scope. cannot read property 'x' of null means the thing you expected to be an object is empty — usually something that was never created, or was created later than you assumed.
The line number is a starting point, not a verdict. It tells you where the program noticed, which is often a little after where the problem began.
Step 2 — Find the line that owns the behaviour
For bugs with no error message — the silent kind, where something is simply wrong — you need a different move: find the one line responsible for the thing you can see.
Work backwards from the symptom. The enemy moves too fast, so find where the enemy's position changes. The score does not update, so find where the score is assigned. Search the codebase for the variable name rather than reading top to bottom; you are looking for the small number of places that write to it.
When a file is too big to hold in your head, cut the problem in half instead: disable the back half of a function and see whether the bug survives. Whichever half still misbehaves is the half to keep halving. Five rounds of this narrows a thousand lines to about thirty.
Step 3 — Make the invisible visible
Most stubborn bugs come from a belief about a value that is not true. You think the speed is 5; it is 50. You think the function runs once; it runs every frame. The fastest way out is to stop believing and start printing.
Print the value right before the line that misbehaves. Print it inside the branch you think is running, to check whether it runs at all. Two or three prints in the right places resolve more bugs than an hour of staring, because they replace a guess with a fact.
The most useful print is often the boring one: console.log("got here"). If it never appears, your problem is not the maths inside the block — it is that the block never runs, and you have been debugging the wrong thing entirely.
Step 4 — Change one thing at a time
Under pressure it is tempting to change four things and re-run. If it works you do not know which fix worked; if it still fails you do not know which change made things worse. Either way you have learned nothing and probably added a second bug.
One change, one run, one observation. It feels slower and is reliably faster.
Step 5 — Prove the fix, do not assume it
The step almost everyone skips. You made a change, the symptom disappeared, you move on — and you never confirmed the change is what fixed it. Sometimes the bug is intermittent and you got a lucky run.
The cheap proof: undo your fix and check that the bug comes back, then redo it. Ten seconds, and it converts a hope into knowledge. If the bug does not come back when you undo the fix, then something else fixed it and you still have a defect you do not understand.
When you are properly stuck
Two moves reliably break a deadlock. First, explain the problem out loud to someone — or to nobody. Describing what you expected and what happened forces you to state the assumption that is wrong, and people routinely solve their own bug halfway through the sentence.
Second, walk away. Not as consolation — because a stuck brain keeps re-running the same wrong model, and stepping away is the only reliable way to drop it. The bug you cannot find at midnight is frequently obvious at breakfast.
If you want to practise this deliberately rather than only when something breaks, the Debugging Real Code module gives you broken files you did not write, which is the realistic version of the skill.
Stop reading, start building
GAMR.dev teaches this in guided steps you can actually finish — one small idea at a time, with hints and answers at every step.