Godot 3 to 4 Converter: Upgrade GDScript Code

Paste a Godot 3 script and this converter rewrites the most common Godot 3 patterns into Godot 4 GDScript: renamed nodes and methods, connect() and emit_signal() to the Signal syntax, yield to await, export and onready to annotations, and setget to property syntax. It lists every change with its line number and flags code that needs a manual rewrite, such as the old Tween node, the File API or move_and_slide() arguments. It is rule-based, not a full converter, so read the warnings before you ship. When spots need manual work, an optional Fix the rest with AI step can rewrite them, which needs a free Ziva account; the rule-based conversion stays free and runs in your browser.

Step 1 of 3: Godot 3 code
Or load a sample:

How to use it

  1. Paste one Godot 3 .gd file into the box, or press a sample button to try it, then press Next.
  2. Turn rule groups on or off, for example keep the old connect() calls by unticking Convert signals to Signal syntax, then press Next.
  3. Check the summary and press Convert to Godot 4.
  4. Press Copy code or Download .gd, then go through Needs manual work and the Changes list line by line.
  5. Optional: under Needs manual work, sign in to your free Ziva account and press Fix the rest with AI to get a version with those spots rewritten, plus a list of what the AI changed. Review it before you use it.

Using Godot 4's built-in project converter

Godot 4 ships its own upgrade tool for whole projects, and you should run it for scenes, resources and project.godot. Back up the project first, because the tool does not make a backup. Open the Godot 4 Project Manager, import the Godot 3 project with Import or Scan, then double-click it (or select it and choose Edit) and pick Convert Full Project in the dialog. Convert project.godot Only is meant for advanced cases where the full conversion fails.

From the command line, preview the planned renames with godot --path /path/to/project --validate-conversion-3to4, then convert with godot --path /path/to/project --convert-3to4. Files over 4 MB or 100,000 lines are skipped by default; pass larger limits as two numbers after the flag, for example --convert-3to4 40000 1000000. Only projects made with Godot 3.0 or later can be converted, and updating to the latest 3.x release first is recommended.

The official tool is regex-based too and cannot handle every case: the Godot docs say scripts will likely still contain errors afterwards. Its rename table, editor/project_upgrade/renames_map_3_to_4.cpp in the Godot source, is where this converter's renames come from. The official tool also renames scene nodes that are named after a renamed class (a node called Sprite becomes Sprite2D), so this converter renames matching $Node paths the same way; untick that rule group if you kept the old node names. One difference: this tool writes the Signal syntax (timeout.connect(_on_timeout)) that the docs recommend, where the official tool keeps the string-based connect("timeout", Callable(self, "_on_timeout")).

What changes between Godot 3 and Godot 4 GDScript

Keywords became annotations: export var is @export var, export(int, 0, 10) is @export_range(0, 10), onready is @onready and tool is @tool, which must sit at the very top of the file. setget became property syntax, var hp = 10: set = set_hp, get = get_hp, and Godot 4 now calls the setter even when the class assigns the variable itself (only inside the setter function does a direct write skip it).

Signals and coroutines are first-class: connect("pressed", self, "_on_pressed") becomes pressed.connect(_on_pressed), extra arguments move to Callable.bind(), emit_signal("died") becomes died.emit(), and yield(timer, "timeout") becomes await timer.timeout. Lifecycle functions such as _ready() no longer call the parent class version automatically, so call super() where you relied on that, and a parent method call written .method() in Godot 3 is super.method() in Godot 4.

Many 3D nodes gained a 3D suffix (Spatial is Node3D, KinematicBody is CharacterBody3D, MeshInstance is MeshInstance3D), and several 2D nodes were renamed (KinematicBody2D is CharacterBody2D, Sprite is Sprite2D, Position2D is Marker2D). On a CharacterBody, move_and_slide() takes no arguments: set velocity, up_direction and the floor properties, call move_and_slide(), and read velocity afterwards. Up direction defaults to Vector2.UP, so most platformers only need move_and_slide().

What still needs a manual rewrite

The Tween node was removed: create tweens in code with create_tween() and tween_property(). The File and Directory classes became FileAccess and DirAccess with a different, partly static API. Window and screen functions moved from OS to DisplayServer, and time functions moved from OS to the Time singleton (this tool converts the common ones such as OS.get_ticks_msec()).

Behavior changes no rename can catch: Array.slice() now excludes its end index, Camera2D zoom is inverted (higher means closer), call_group() runs immediately instead of deferred, and randomize() is called automatically when the project starts, so set a seed yourself if you need repeatable randomness. Shaders need their own upgrade (hint_color and hint_albedo became source_color, and .shader files must be renamed to .gdshader).

Frequently asked questions

Can I convert a whole Godot 3 project to Godot 4?
Yes, with the converter built into Godot 4: back up the project, open it from the Godot 4 Project Manager and choose Convert Full Project, or run the editor with --convert-3to4. This web tool is for one script at a time, when you want to see exactly what changed or port code you copied from a Godot 3 tutorial.
Is this a full Godot 3 to 4 converter?
No. It is a rule-based rewrite of the most common patterns, with renames taken from Godot's own upgrade table. It never touches strings or comments, lists every line it changed, and warns about APIs such as Tween, File and move_and_slide_with_snap() that need a manual rewrite. The optional AI step can rewrite those spots for you, but test the result in Godot 4 before relying on it either way.
How do I convert yield to await in Godot 4?
Replace yield(object, "signal_name") with await object.signal_name, for example await get_tree().create_timer(1.0).timeout. When you waited for another function with yield(some_function(), "completed"), write await some_function() instead.
Why does my converted script say velocity is already defined?
CharacterBody2D and CharacterBody3D have a built-in velocity property in Godot 4, so a var velocity declared in your script clashes with it. This converter removes a plain var velocity = Vector2() line from scripts that extend a KinematicBody or CharacterBody, and warns when the declaration has a starting value you need to move to _ready().
Does the converter upload my code?
Not for the rule-based conversion: it runs entirely in your browser and needs no account. Only if you press Fix the rest with AI are the converted script and the manual-work notes sent to Ziva's servers; that step needs a free Ziva account and counts toward your Ziva plan.

See all tools