Game Development with Godot & GDScript Module 9
Classes, memory and custom resources interview questions
Interview questions on classes, memory and custom resources: warm-ups, then what each harder question tests and how a good answer starts.
Warm-up questions
Short questions with short answers, each answered in full.
-
Fresher
What does class_name do in GDScript, and how does another script use a class that has none?
-
Fresher
When does a GDScript setter run, and when does it not?
Answered in the lesson Properties, static members and abstract classes
-
Fresher
What does a lambda capture in GDScript, and when?
-
Fresher
How is memory managed in Godot, and when must you free an object yourself?
Answered in the lesson Memory: Object, RefCounted, Node, Resource
-
Fresher
What is a custom resource in Godot, and when is it better than a Dictionary or a JSON file?
Answered in the lesson Custom resources and data-driven design
Questions with model answers
What each question tests, the first step of a good answer and the follow-ups to expect.
-
Fresher to mid
A teammate adds Ghost, which extends your Enemy class and has its own _init(p_name) that sets a flag. In playtests ghosts appear with no name and 0 hit points, and Godot reports no error. What went wrong, and how do you keep it from happening again?
- What it tests
- Knowing that a subclass's _init() replaces the parent's and runs it only through super(), and turning a silent bug into a test or a review rule.
- First step
- Print enemy_name and hp on the first line of Ghost._init(). They are already empty and 0 there: Enemy's _init() never ran, because Ghost's replaced it and has no super(p_name) call. Godot accepts this without a warning, so nothing else will point at it.
- Follow-ups
-
- Why does Bat, which has no _init(), get its name and 20 hp?
- Where must super() go, and what may run before it?
- How would a test catch this for every enemy type?
From the lesson Classes, inheritance and class_name
Model answer, Pro. Model answers open with any pass; prices are in the notice on this page.Opening the model answers with your pass…
Model answers open with any MySmartCoPilot pass.
- Pro pass · 1 week₹79$2.99
- 30 days₹179$5.99
- 1 year₹1,699$45
One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.
Passes can’t be bought right now, so the model answers can’t be opened at the moment. If you have a pass, enter your licence key.
It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).
In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 2 minutes
-
Mid to senior
The combat script decides what a hit does with if weapon is Sword, elif weapon is Bow and eight more branches, and every new weapon means editing it. How do you restructure it, and when is an is check still the right tool?
- What it tests
- Replacing type switches with overridden functions on a base class, keeping one pipeline in the base, and recognising where a type check is still honest.
- First step
- Find what the branches compute: here each one decides how much armour blocks. Make that a function of the base class, blocked(armour), override it in each weapon, and let one pipeline in Weapon call it, so the combat script calls weapon.hit(armour) and never asks for the type.
- Follow-ups
-
- Two weapons need the same special rule. Where does it go?
- How do you stop a subclass from replacing the whole pipeline?
- Which checks are still fine as is checks?
From the lesson Classes, inheritance and class_name
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Fresher to mid
A health bar has an exported hp whose setter writes the text of a child Label through an @onready variable. The game stops with an error about a base object of type Nil as soon as the scene loads, yet changing hp later works. Explain the order of events and fix it.
- What it tests
- Knowing when a scene applies exported values, when @onready variables get theirs, and how to write a setter that works in both states.
- First step
- Print is_node_ready() and label at the top of the setter, and note which call the error comes from: the one made while the scene loads, or a later one made by code. Then compare when the scene file's value is applied with when an @onready variable gets its value.
- Follow-ups
-
- Why does the same setter work when code sets hp after the node is in the tree?
- Would await ready inside the setter be a good fix?
- How would you test the fix without opening the editor?
From the lesson Properties, static members and abstract classes
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 2 minutes
-
Mid to senior
Every Bullet appends itself to static var all: Array[Bullet] so that a debug overlay can show how many exist. After ten levels the game uses far more memory than at the start, though each level frees its own list of bullets. Why, and what do you change?
- What it tests
- Understanding reference counting with static state, measuring a leak with the object monitor, and choosing an owner for objects instead of the class.
- First step
- Print Performance.get_monitor(Performance.OBJECT_COUNT) and all.size() after each level, and compare how the two numbers grow. Then ask which variable still refers to a bullet once its level's own list is gone.
- Follow-ups
-
- Why does each level freeing its own list not free the bullets?
- What would you keep on the class instead?
- Does @static_unload help here?
From the lesson Properties, static members and abstract classes
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 2 minutes
-
Mid to senior
Doors, chests and talking guards can all be used by the player. One teammate wants an @abstract Usable base class, another wants has_method("interact"), a third a group. Which do you choose for which objects, and what does each one fail to catch?
- What it tests
- Comparing the contracts GDScript offers by what they check and when, and fitting them to single inheritance and to objects from outside the team.
- First step
- List the objects, what each one extends and whether all of them come from your own scripts. Then ask, for each contract, when a misspelt method name would show up: before the game runs, when the line runs, or never.
- Follow-ups
-
- What happens to a misspelt method name under each contract?
- How do you get early errors for nodes of different engine classes?
- Where does a plugin's object fit?
From the lesson Properties, static members and abstract classes
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 2 minutes
-
Fresher to mid
A combo meter is built with make_combo(), which declares var hits := 0 and returns a lambda that adds 1 to hits and returns it. Every hit shows a combo of 1. Why, and give two fixes with their trade-offs.
- What it tests
- Knowing that a lambda captures local variables by value at creation, and keeping state that must change in a shared container or an object.
- First step
- Print hits inside the lambda before and after the increment on two calls. Both calls start from 0: the lambda copied hits when make_combo() created it, each call changes only its own copy, and the copy it keeps never changes.
- Follow-ups
-
- Why does the parser not stop this?
- When is a class better than a lambda with a dictionary?
- How would a test catch it?
From the lesson Lambdas, Callables and capture rules
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 2 minutes
-
Fresher to mid
A level-select menu makes 30 buttons in a loop and one handler must know which level was pressed. Show two ways to pass the level number, and say which one you can disconnect later without keeping anything, and why.
- What it tests
- Using bind() and lambdas to carry extra data into a signal handler, and knowing how Callables compare when a connection must be found again.
- First step
- Start from what pressed passes: nothing. The handler needs one value per button, so compare the two ways a Callable can carry it: a lambda made in the loop, or a method Callable with the value attached to it.
- Follow-ups
-
- Does a lambda made in the loop see the right level?
- What if the handler also needs the signal's own arguments?
- What happens to the connections when a button is freed?
From the lesson Lambdas, Callables and capture rules
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 2 minutes
-
Mid to senior
A boss fight connects a repeating timer's timeout to a lambda that calls enemy.attack(). After the enemy dies and is freed, the log shows an error about a freed lambda capture every second. Explain what is going on and fix it.
- What it tests
- Knowing how method Callables and lambdas behave when their object is freed, which connections Godot removes, and how to guard or restructure the call.
- First step
- Read the first error: it names a lambda capture that was freed. Find the variable the lambda captured and what happened to its object when the enemy died, then check what the timer's connection still holds.
- Follow-ups
-
- Why does checking is_valid() on the Callable not help?
- Which connection would Godot have removed by itself?
- How do you find every such connection in a large project?
From the lesson Lambdas, Callables and capture rules
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 2 minutes
-
Fresher to mid
A game's memory grows by a few megabytes every time the player finishes a level and starts the next, and never comes back. The scene tree looks the same each time. How do you find what leaks, step by step, without a profiler?
- What it tests
- Measuring a leak per unit of work with the object monitors, naming the leaked objects, and knowing which kinds of object each rule of freeing misses.
- First step
- Read Performance.get_monitor(Performance.OBJECT_COUNT) and OBJECT_ORPHAN_NODE_COUNT before a level and after it, in a debug build, and repeat for three levels. A leak shows as the same growth each time, and the two numbers say whether it is nodes outside the tree or other objects.
- Follow-ups
-
- The orphan count is 0 but OBJECT_COUNT still grows. What next?
- How do you name the objects that are left?
- How do you stop the leak from coming back?
From the lesson Memory: Object, RefCounted, Node, Resource
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 2 minutes
-
Mid to senior
Squads are RefCounted and hold their soldiers in an array; each soldier keeps a variable pointing to its squad. When a squad is disbanded and no code refers to it, neither the squad nor its soldiers are ever freed. Explain why and give two fixes, with their trade-offs.
- What it tests
- Understanding reference counting and reference cycles, using weak references, and choosing between them and an explicit teardown.
- First step
- Count the references: the squad is held by each soldier, and each soldier by the squad's array. Once no outside variable holds the squad, ask whether either count can still reach zero.
- Follow-ups
-
- How would you see this cycle in a running game?
- What changes when the soldiers are nodes in the tree?
- Does connecting the soldiers to a squad signal make it worse?
From the lesson Memory: Object, RefCounted, Node, Resource
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Fresher to mid
A crate scene has a CollisionShape2D with a RectangleShape2D. When one crate is upgraded at run time, its code sets the shape's size, and every crate in the level, and every crate spawned later, grows too. Why, and how do you give one crate its own size?
- What it tests
- Knowing that resources are shared between instances by default, and choosing between resource_local_to_scene and duplicate() with their costs.
- First step
- Compare the shape objects of two crates with ==. If they are the same object, the crates share one resource, and a change through either crate changes it for both. Then ask where that one object lives.
- Follow-ups
-
- Why do crates spawned later also grow?
- When would you choose Local To Scene over duplicate()?
- What does a copy per crate cost?
From the lesson Memory: Object, RefCounted, Node, Resource
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 2 minutes
-
Mid to senior
An item database scans res://items with DirAccess and loads every file ending in .tres. In the editor the shop lists 40 items; in the exported game it lists none. What happened, and how do you build the list so it works in both?
- What it tests
- Knowing how exported projects store resources, using ResourceLoader rather than DirAccess and FileAccess for them, and testing data loading in an exported build.
- First step
- Print what the folder scan returns in the exported game, next to what it returns in the editor. Then compare the file names, and read what the DirAccess reference says about res:// folders after export.
- Follow-ups
-
- Why did the editor hide the problem?
- How do you check that an icon path exists in the exported game?
- What should the game do when an item file fails to load?
From the lesson Custom resources and data-driven design
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 2 minutes
-
Mid to senior
Designers edit 300 item resources in the Inspector, and every week a mistake reaches a playtest: two items with one id, a negative price, an icon that was renamed, a loot table whose weights do not match its entries. Design a check that stops these before a build, and say where it runs.
- What it tests
- Turning the rules the game relies on into a validator over the data, choosing where it runs, and making its report useful to designers.
- First step
- List the rules the game relies on for every item and loot table. Then find the earliest moment when all of the files can be read together, outside the game's own code paths.
- Follow-ups
-
- Why do the Inspector's export hints not prevent these mistakes?
- How do you report a problem so that a designer can fix it alone?
- How does the check keep up with new kinds of mistakes?
From the lesson Custom resources and data-driven design
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 2 minutes
All Game Development with Godot & GDScript interview questions · The Game Development with Godot & GDScript track