If you have asked Copilot, Claude, or ChatGPT to write Godot code in the last six months, you have hit this: the generated code looks reasonable, compiles clean, and then fails at runtime because the function name does not exist. Godot 4 shipped in March 2023 with a completely rewritten GDScript and dozens of renamed APIs. Training data for most LLMs still overrepresents Godot 3 tutorials. The result is an asymmetric failure mode: the code looks right, even to a reviewer who has not touched Godot 3, and you only find out it is broken when you run the game.
Here are seven of the most common API calls where AI assistants hallucinate the Godot 3 version, with the Godot 4 replacement and a short note on why each one specifically keeps tripping up the models.
1. deg2rad → deg_to_rad
The old name, deg2rad(angle), still appears all over Reddit and StackOverflow posts from 2020 to 2022. In Godot 4 it is deg_to_rad with underscores. Same for rad2deg → rad_to_deg.
This is the single most-hallucinated function in my experience. The numeric "2" in the old name is legacy from the C++ style used in older Godot versions, and the rename to a readable verb was one of the first things the Godot 4 style guide pushed. LLMs still reach for the short form because it is shorter and because the training data is denser.
2. KinematicBody2D → CharacterBody2D
Godot 3 had KinematicBody2D and KinematicBody (for 3D). Godot 4 renamed both to CharacterBody2D and CharacterBody3D. The internal semantics also changed: move_and_slide() no longer takes a velocity argument; you set velocity as a property first, then call the method.
AI assistants get the class rename right about half the time. Where they fail consistently is the call signature. You will see generated code like move_and_slide(velocity, Vector2.UP) which is valid Godot 3 and a runtime error in Godot 4.
3. set_shader_param → set_shader_parameter
ShaderMaterial.set_shader_param(name, value) became set_shader_parameter(name, value). The get_shader_param pair also renamed.
This one is tricky because shader workflow tutorials from the Godot 3 era are high-quality and heavily SEO-optimized. When an AI reaches for shader code, it reaches for the tutorial it was trained on, and that tutorial says set_shader_param.
4. BUTTON_LEFT → MOUSE_BUTTON_LEFT
Mouse button constants got a prefix. BUTTON_LEFT, BUTTON_RIGHT, BUTTON_MIDDLE, and the wheel constants are now MOUSE_BUTTON_*.
Why it matters: this is a runtime-only failure. If your input handler checks event.button_index == BUTTON_LEFT, the comparison never matches because BUTTON_LEFT resolves to a different numeric value (or doesn't exist at all, depending on how the constant is scoped).
5. rand_range → randf_range / randi_range
Godot 3's rand_range(min, max) returned a float. Godot 4 splits this into randf_range (float) and randi_range (int). The type-explicit naming is good. The fact that every AI assistant still generates rand_range is not.
6. yield() → await
Godot 3 used a custom yield() function for coroutines: yield(get_tree().create_timer(1.0), "timeout"). Godot 4 replaced this with standard await: await get_tree().create_timer(1.0).timeout.
This is the largest syntactic shift in the list, and the one where AI code breaks most visibly. yield() in Godot 4 is a Python-style function that does not exist. You get an immediate parse error, which at least makes it easy to catch. Compare that to the mouse button case, which silently fails forever.
7. Directory → DirAccess / FileAccess
The global Directory class, and its pair File, were both removed in Godot 4. The replacement is DirAccess and FileAccess, both with static factory methods: DirAccess.open(path) and FileAccess.open(path, FileAccess.READ).
The old class-based API used var f = File.new() followed by f.open(path, File.READ). AI assistants still reach for this because File I/O is one of the most commonly documented patterns and the old one was in wide circulation for years.
Why this keeps happening
Two forces make Godot particularly prone to this failure mode:
Training data density favors Godot 3. Godot 4 launched in March 2023. The bulk of high-quality community tutorials, Reddit answers, and StackOverflow posts were written before that. When an LLM computes "what is the most likely next token after shader_," the frequency of param in the training corpus still dominates parameter.
Godot 4 minor versions keep changing signatures. The Godot 4.5 release notes mention variadic function signature changes that broke compatibility with 4.3 and 4.4. Even a model with training data that ends in late 2025 has not seen enough 4.5 examples to correctly weight them.
The result: the newer your Godot version, the worse any general-purpose coding assistant performs. This is not a problem that gets solved by a bigger context window. It gets solved by giving the model the current API, either through retrieval-augmented generation against Godot's docs or through a purpose-built plugin that can run the code and test the output.
How to work around it
Three things help:
Paste the Godot 4.x breaking changes list into your system prompt. It is a short file maintained by a Godot contributor and it catches most of the renames. A 2-page addendum to the system prompt is worth more than any clever reasoning you can add.
Use an agent that runs the code it generates. A parse error catches
yield(). A runtime test catchesBUTTON_LEFT. The mouse button case specifically cannot be caught by any static linter because the comparison is syntactically valid. Tools like Ziva solve this by running the generated code against a live Godot editor and surfacing runtime errors back to the model, but any setup that executes the code will catch the silent-failure cases that matter most.Prefer static typing. Godot 4 supports
var velocity: Vector2. Typed variables turn some of these hallucinations into editor errors. It does not help with constants or function names, but it catches a surprising number of incompatible signature cases.
If you are shipping a Godot game in 2026 and letting AI generate scripts, the practical move is to pair any generation step with an execution step. "Does it compile" is not the right test. The right test is "does the node still behave correctly when you run the scene." Everything else is theater.
Top comments (0)