Unity C# to GDScript Converter: Port Unity Scripts

Paste a Unity C# MonoBehaviour script and this tool rewrites it as typed GDScript for Godot 4.3 or later: Update becomes _process, FixedUpdate becomes _physics_process, GetComponent becomes a child node reference, UnityEvents become signals and coroutines become await. Next to the script you get the list of Unity to Godot mappings it used and the things you still have to do by hand, such as child nodes and input actions. The conversion needs a free Ziva account; treat the result as a starting point and test it in Godot.

Step 1 of 3: Unity script
Or load a sample:
0 / 12,000 characters

How to use it

  1. Paste one Unity C# script into the box, or press Player controller or Health component to load a sample, then press Next.
  2. Pick the node the script should extend (CharacterBody2D, CharacterBody3D, Node2D, Node3D or Area2D), or keep Auto, then press Next.
  3. Check the summary, sign in to your free Ziva account if asked, and press Convert to GDScript.
  4. Press Copy code or Download .gd, then go through Manual work and API mappings before you run the script.
  5. Press Generate another if you want a different version of the same conversion.

How Unity concepts map to Godot

A Unity GameObject collects components; a Godot object is a tree of nodes, each with one job. A player is a CharacterBody2D with a Sprite2D, a CollisionShape2D and a Camera2D as children, and the script is attached to the root node. That is why GetComponent<SpriteRenderer>() turns into a child node reference such as @onready var sprite: Sprite2D = $Sprite2D, and why the converter lists the child nodes you need to add. Godot's own docs describe scenes as filling the role of both prefabs and scenes from other engines: save the node tree as a scene, then instance it as often as you like.

The lifecycle maps closely. Awake and Start become _ready(), Update becomes _process(delta), which runs every frame, and FixedUpdate becomes _physics_process(delta), which runs at a fixed rate of 60 times per second by default. Time.deltaTime is the delta parameter. Godot's docs say Resource scripts are similar to Unity's ScriptableObjects, so data assets become a Resource with a class_name.

Events and coroutines get simpler. A UnityEvent or C# event becomes a signal declared at the top of the script (signal died), fired with died.emit() and listened to with died.connect(_on_died). A coroutine that waits with yield return new WaitForSeconds(0.5f) becomes a normal function that calls await get_tree().create_timer(0.5).timeout. Tags become groups, checked with is_in_group("enemies").

Differences that break a straight port

In Godot 2D the Y axis points down, and Vector2.UP is (0, -1). A Unity jump that sets a positive Y velocity needs a negative one in Godot, and so does gravity code written for Y up. 3D is Y up in both engines. Unity 2D also measures in world units while Godot 2D measures in pixels, so speeds, jump forces and distances need new values even when the code is right.

A CharacterBody2D or CharacterBody3D has a built-in velocity property and no automatic gravity: add get_gravity() * delta to velocity while not is_on_floor(), then call move_and_slide() with no arguments. A Physics2D.OverlapCircle ground check usually becomes is_on_floor(). Unity's named input axes become input actions: Input.GetAxisRaw("Horizontal") maps well to Input.get_axis("ui_left", "ui_right"), but a custom action such as "jump" must be added under Project Settings > Input Map before is_action_just_pressed("jump") works.

Small API semantics differ too. Unity's Random.Range(0, 10) with integers never returns 10, while Godot's randi_range(0, 10) can, so integer ranges shift by one. Animator parameters have no one-line equivalent; an AnimationTree or AnimationPlayer has to be set up in the editor, so the converter marks those calls with TODO comments.

GDScript or C# in Godot

Godot also supports C#, through the separate .NET edition of the editor. Keeping C# saves rewriting syntax, but every Unity API call (MonoBehaviour, GetComponent, Rigidbody2D, Input) still has to change to Godot's API, so most of the porting work stays. Godot's docs also note that C# projects made with Godot 4 cannot be exported to the web yet, which matters for browser games and game jams.

This tool converts to GDScript, Godot's built-in language, which needs no extra install and exports to every platform Godot supports. Godot has no importer for Unity scripts or scenes, so port one script at a time: convert it, build the node tree it expects, run the scene, and fix what the editor reports. 3D models move more easily, since Godot imports FBX and glTF files directly.

Frequently asked questions

Can Godot import a Unity project?
Not directly. Godot does not include an importer for Unity projects, scenes or C# scripts. 3D models in FBX or glTF format and textures import as they are, but scripts have to be rewritten for Godot's API and scenes rebuilt as Godot node trees. This tool speeds up the script part, one file at a time.
Is the converted GDScript ready to use?
Treat it as a starting point. The AI rewrites the logic and names the Godot APIs it used, but it cannot see your scenes, so child node paths, input actions, animation setup and tuning values usually need changes. Open the script in Godot, fix anything the editor reports, and test the scene before relying on it.
Does the Unity to Godot converter cost anything?
The conversion needs a free Ziva account, and each conversion counts toward your Ziva plan. Your script is sent to Ziva's servers to make the conversion, so only paste code you are allowed to share.
What is the Godot equivalent of Update and FixedUpdate?
Update is _process(delta), which Godot calls every frame, and FixedUpdate is _physics_process(delta), which runs at a fixed physics rate of 60 times per second by default. Use the delta parameter wherever the Unity code used Time.deltaTime.
What replaces GetComponent in Godot?
Godot splits an object into child nodes instead of components, so GetComponent<T>() becomes a reference to a child node, usually @onready var name: Type = $ChildName. For objects elsewhere in the scene, use an exported NodePath or node variable, a group with get_tree().get_first_node_in_group(), or a signal.

See all tools