How to Port a Unity Project to Godot 4

A practical 2026 playbook for porting a Unity project to Godot 4.7: audit, asset pipeline, vertical slice, and what does not auto-convert.

Unity to Godot porting playbook
On this page

Porting a Unity project to Godot is less about translating every line and more about proving one slice, then widening it. This playbook sequences the work so risk shows up early: audit what you actually depend on, get the project and input working, bring assets across deliberately, rebuild one vertical slice end to end, and prove the export before you let feature work run ahead of the pipeline.

Decide Whether to Port or Rebuild

Unity and Godot do not share an architecture, so "porting" rarely means moving files across and recompiling. Unity organizes a game around GameObjects, attached MonoBehaviour components, and ScriptableObjects for shared data. Godot organizes a game around scenes, a node tree, typed scripts, signals, and Resources. A GameObject with six components does not become one Godot node with six scripts bolted on; it becomes a small scene where each responsibility gets a node or a script that owns it. Treat the move as a supervised rebuild that reuses proven design decisions and source assets, not a mechanical file conversion.

That distinction changes what you optimize for early. If you plan a straight line-by-line port, you will spend the first weeks fighting the engine instead of shipping the game, because Unity idioms like singleton managers, GetComponent lookups, and prefab variants do not have a one-to-one Godot equivalent. Read the engine comparison before committing a timeline, and use it to explain to stakeholders why a 3-month Unity feature backlog does not translate into a 3-month Godot port.

Audit Dependencies and Plugins First

Before writing any Godot code, list every Asset Store package, native plugin, and Unity subsystem the project actually uses at runtime: analytics, IAP, ads, a specific physics behavior, Timeline, Cinemachine, the Input System package, NavMesh, and any third-party networking or save framework. For each one, decide whether Godot has a built-in equivalent, a maintained community addon, or nothing, and mark the gap now rather than discovering it mid-port. This single afternoon of work is what prevents a rewrite from stalling three weeks in on a dependency nobody accounted for.

  • Rendering and shaders: custom shader graphs and post-processing stacks need to be rebuilt in Godot's shading language or VisualShader, not copied.
  • Input: the Input System package's action maps map conceptually to Godot's Input Map, but bindings must be recreated by hand.
  • Physics behavior: Jolt-backed 3D physics in Godot 4 behaves differently from PhysX; re-tune forces, masses, and joints rather than assuming numbers transfer.
  • Networking, save systems, and analytics SDKs: confirm a Godot-compatible replacement exists before scoping the rest of the schedule around it.

Split the audit into three lists: what has a direct Godot feature, what needs a community addon or GDExtension, and what has to be written from scratch. That third list is the real migration budget. Use the equivalents reference while auditing so you are checking against verified Godot 4.7 APIs instead of guessing from memory.

Set Up the Godot Project and Input Map

Create the Godot project and match the fundamentals before writing gameplay logic: viewport resolution and stretch mode, default 2D or 3D scale, physics tick rate if the Unity project relied on a specific fixed timestep, and collision layer names. Skipping this step means every early test scene is measuring the wrong thing, because a mismatched viewport or physics rate will make movement and camera work feel wrong for reasons that have nothing to do with your gameplay code.

Then rebuild input as named actions instead of hard-coded keys. Open Project Settings, go to the Input Map tab, and create an action for every gameplay intent your Unity Input System action map already defines: move, jump, interact, pause. Read them with the Input singleton rather than checking a specific key or button, which is the same discipline the Input System package was already pushing you toward.

gdscript
# player.gd — read named actions, not raw keys
extends CharacterBody2D

@export var speed := 260.0

func _physics_process(_delta: float) -> void:
    var direction := Input.get_vector("move_left", "move_right", "move_up", "move_down")
    velocity = direction * speed
    move_and_slide()

Do this before touching gameplay scripts. An input map that already matches your control scheme means every ported system after this point can assume named actions exist, instead of every script separately deciding how to read a key.

Order the Port by Risk, Not by Folder

Signature lab · Migration planner

Sequence your Unity port

Click each step in the order you would tackle it.

Your order will appear here.

The instinct is to port folder by folder, in whatever order the Unity project happens to organize scripts. That order optimizes for how the old project looked, not for what will actually break your schedule. Sequence the work by risk instead: the dependency audit first, because it tells you which unknowns exist; the project and input setup second, because everything else depends on it; assets third, so scenes have something real to look at while you work; one vertical slice fourth, to prove input, movement, one data system, and one UI surface work together end to end; the remaining systems fifth, built against that proven slice instead of in isolation; and the export pipeline last, proven before feature work is declared done. Getting this order backwards is the most common reason Unity-to-Godot ports stall — teams spend a month polishing a system that later turns out to depend on an export limitation nobody checked.

Use the planner below to put your own project's systems in that same audit-then-risk order before you start moving files. A plan that is only in your head is easy to reorder under deadline pressure back into folder order; a plan you can point at during a status update is much harder to quietly abandon.

Bring Assets Across the FBX to glTF Pipeline

Godot 4 imports FBX files directly through the built-in ufbx library, so a model exported from Blender or Maya as FBX will generally import without an external converter. glTF 2.0 remains the format Godot's documentation recommends when you have a choice, because it round-trips more predictably and avoids any dependency on a proprietary format. If your Unity project's source models still live in your DCC tool, re-exporting the ones you actually reuse as glTF is worth the extra step.

If instead you are pulling assets out of an existing Unity project wholesale — scenes, prefabs, materials, and meshes already baked into .unitypackage or Library form — the community addon unidot_importer is the closest thing to an automated bridge: it translates Unity .unity scenes and .prefab files into Godot .tscn scenes, and converts materials, textures, and humanoid armatures. It still relies on the external FBX2glTF tool internally to convert meshes, and its own documentation is explicit that scripts and shaders are not converted and must be ported by hand, and that Canvas/UI content is not supported at all. Treat it as an asset accelerator, not a project importer.

Rebuild One Vertical Slice End to End

Pick the smallest real gameplay loop in the project — the one that involves player input, movement, one interactive object, one piece of UI, and one save or tuning value — and rebuild only that in Godot before touching anything else. This is the single highest-leverage step in the whole playbook, because it is the first point where you find out whether your dependency audit was actually complete. A slice that runs end to end tells you the input map works, the physics feel is close enough, one data-driven system (an item, a stat, an enemy) reads from a Godot Resource instead of a ScriptableObject, and one UI surface updates from a signal instead of a direct reference.

gdscript
# pickup.gd — a small, self-contained slice of gameplay
extends Area2D

signal collected(points: int)

@export var points := 10

func _on_body_entered(body: Node) -> void:
    if body.is_in_group("player"):
        collected.emit(points)
        queue_free()

Resist the temptation to widen scope before the slice is solid. A pickup that emits a signal, a HUD that listens and updates a label, and a player that moves on named input actions together prove more about your Godot architecture than a week spent converting unrelated scripts. Use the translation lab to check unfamiliar C# patterns against their GDScript equivalent while you rebuild the slice, and read scenes versus prefabs if deciding where one scene boundary should end and another begin still feels arbitrary.

  • Input reaches the player through named actions, not hard-coded keys.
  • One interactive object emits a signal that a separate node listens to, mirroring a Unity event but without a direct component reference.
  • One data value loads from a Godot Resource instead of a ScriptableObject.
  • One UI element updates from that signal instead of polling every frame.

Know What Does Not Auto-Convert

Being explicit about what never converts automatically saves the schedule from a slow, quiet failure mode where a plugin appears to have "handled" something that it only partially touched. Four categories consistently need a hand rewrite rather than a mechanical translation.

  • Shaders: Unity Shader Graph and HLSL shaders have no automated path into Godot's shading language or VisualShader graph; expect to recreate visual effects from the underlying technique, not the source file.
  • Netcode: Unity Netcode for GameObjects or Mirror architecture does not map onto Godot's high-level multiplayer API; ownership, RPCs, and synchronization need a fresh design against Godot's networking model.
  • Editor scripts and custom tooling: Unity Editor windows, custom inspectors, and asset pipeline scripts are C# against the UnityEditor API and have to be rebuilt as Godot EditorScript or plugin tooling if you need the equivalent workflow at all.
  • Gameplay code and MonoBehaviour lifecycle: Awake/Start/Update timing, GetComponent lookups, and singleton managers do not translate line by line into Godot's _ready()/_process() and node-ownership model, even when a tool copies the file across.

If a conversion tool reports success on any of these four categories, read that as "the file exists in the new project," not "the behavior works." Verify each one against a running scene before counting it as migrated.

Prove the Export Before Feature Freeze

Set up an export preset for your actual target platform in the very first week, not the last one. In the Godot editor's Export dialog, add a preset for the platform, then install the matching export templates through Editor → Manage Export Templates (or download the offline template package if your network is restricted). The dialog will refuse to export for a platform until any missing SDK or template dependency is resolved, so this step surfaces platform blockers immediately instead of at the end of the project.

Export the vertical slice itself, on real target hardware if you can, before declaring feature work done or expanding beyond the slice. A build that only ever runs from the editor has not actually proven the port; export settings, included resources, and platform-specific behavior differences from Unity's build pipeline only show up once you produce a real package and run it outside the editor. Treat a successful export of the small slice as the gate that unlocks widening the port to the rest of the project, not a checkbox left for the end.

Frequently asked questions

Can I automatically convert a Unity project to Godot?
Only assets, and only partially. Tools like unidot_importer import .unitypackage art and scenes into Godot 4, but gameplay code, shaders, and editor tooling must be rewritten.
Should I port or rebuild?
Rebuild the gameplay in a vertical slice and port only assets. A mechanical line-by-line port usually costs more than a focused rebuild because Godot's node/scene/signal model differs from Unity's component model.
Verification notes

Sources and revision context

New for the migration spine; sequences a Unity→Godot 4.7 port around a proven vertical slice.