Godot 4 для Unity-разработчика: что переносится, а что придётся переучивать
Прошлой зимой я запустил пет-проект на Godot 4 после девяти лет в Unity. Первая неделя была странная: вроде всё знакомо — сцены, ноды, скрипты — но руки тянутся к привычным кнопкам, которых тут нет, а привычные паттерны иногда работают наоборот. Если ты Unity-разработчик и думаешь попробовать Godot 4 (или вынужден из-за лицензионной паники 2023 года), вот честная карта: что ты перенесёшь без проблем, что придётся переучивать с нуля, а где Godot реально удобнее.
Я ориентируюсь на Godot 4.3 и Unity 6 (6000.x). Если у тебя 4.0 или 4.1, часть деталей будет отличаться, но общая картина та же.
Сцена и нода — не то же самое, что GameObject и Component
Это первое, обо что спотыкаются все. В Unity у тебя есть GameObject, на него вешаются Component'ы, и логика обычно живёт в скриптах-компонентах. В Godot всё — это Node. Sprite2D, RigidBody3D, AudioStreamPlayer — всё ноды. Сцена — это просто дерево нод, сохранённое в файл .tscn.
Главное отличие: в Godot ты не добавляешь поведение к объекту через компоненты, ты композируешь объект из дочерних нод. Хочешь врага с хитбоксом и звуком удара? Это будет CharacterBody2D с дочерними CollisionShape2D, AnimatedSprite2D, AudioStreamPlayer2D, Area2D для хитбокса и так далее.
Сначала это раздражает: дерево разрастается, и кажется, что простая Unity-сцена с пятью компонентами на одном GameObject превратилась в десять вложенных нод. Но через пару недель привыкаешь, и читать структуру становится проще — иерархия сама документирует, что объект умеет.
Ещё момент: префабы в Godot называются сценами. Любая .tscn может быть инстансирована как префаб, и любую часть текущей сцены можно превратить в отдельную сцену через правый клик → Save Branch as Scene. Никаких префаб-вариантов: вместо них наследование сцен, которое работает похоже, но с другими правилами разрешения переопределений.
C# работает, но GDScript — гражданин первого сорта
Если ты, как и я, привык к C#, хорошая новость: Godot 4 поддерживает C# через .NET 8. Плохая — поддержка слегка отстаёт. Hot reload работает не везде, экспорт под Web с C# до сих пор хромает (на момент 4.3 — официально не поддерживается), а часть документации и плагинов написана только под GDScript.
GDScript внешне напоминает Python, но это полноценный язык со статической типизацией. Через неделю ты пишешь на нём быстрее, чем на C#, потому что компилятор-фронтенд встроен в редактор и подсказки работают мгновенно. Вот типичный кусок:
extends CharacterBody2D
@export var speed: float = 200.0
@export var jump_velocity: float = -400.0
func _physics_process(delta: float) -> void:
if not is_on_floor():
velocity += get_gravity() * delta
if Input.is_action_just_pressed("jump") and is_on_floor():
velocity.y = jump_velocity
var direction := Input.get_axis("move_left", "move_right")
velocity.x = direction * speed
move_and_slide()
Аналог на C# в Godot:
using Godot;
public partial class Player : CharacterBody2D
{
[Export] public float Speed { get; set; } = 200.0f;
[Export] public float JumpVelocity { get; set; } = -400.0f;
public override void _PhysicsProcess(double delta)
{
var velocity = Velocity;
if (!IsOnFloor())
velocity += GetGravity() * (float)delta;
if (Input.IsActionJustPressed("jump") && IsOnFloor())
velocity.Y = JumpVelocity;
var direction = Input.GetAxis("move_left", "move_right");
velocity.X = direction * Speed;
Velocity = velocity;
MoveAndSlide();
}
}
Заметь две вещи. Во-первых, классы — partial, потому что Godot генерирует boilerplate отдельным файлом. Во-вторых, [Export] — это аналог [SerializeField] из Unity, поле появляется в инспекторе.
Мой совет: если проект большой и ты ценишь экосистему .NET (NuGet, профайлеры, Rider), бери C#. Если пет-проект и ты хочешь итерировать быстро — попробуй GDScript хотя бы на пару прототипов. Я в итоге пишу гибридно: тяжёлая логика на C#, glue-скрипты на GDScript.
MonoBehaviour vs Node: lifecycle почти один в один
Здесь Unity-разработчик чувствует себя дома. Сравни:
Awake/Start→_ready(вызывается, когда нода и все её дети готовы)Update→_process(delta)FixedUpdate→_physics_process(delta)OnDestroy→_exit_treeOnEnable/OnDisable→_enter_tree/_exit_tree+ сигналы видимости
Главное отличие: в Godot delta приходит параметром, а не через Time.deltaTime. Мелочь, но первые дни рука тянется к статическому полю.
И ещё: в Godot нет Awake отдельно от Start. Если тебе нужна инициализация до того, как другие ноды получат ссылку на твою, используй _init (вызывается в конструкторе) или паттерн с @onready:
@onready var sprite: Sprite2D = $Sprite2D
@onready var hitbox: Area2D = $Hitbox
Это синтаксический сахар, который раскрывается в присваивание внутри _ready. Очень удобно — никаких GetComponent в стартовых функциях.
Сигналы вместо UnityEvent и delegate-спагетти
В Unity для слабосвязанной коммуникации обычно берут UnityEvent, System.Action или какую-нибудь шину сообщений из ассет-стора. В Godot встроенная штука — сигналы. Это, по сути, типизированные события на уровне движка, и они интегрированы с редактором.
Пример: у тебя есть кнопка, ты хочешь повесить на неё обработчик. В коде:
func _ready() -> void:
$Button.pressed.connect(_on_button_pressed)
func _on_button_pressed() -> void:
print("clicked")
Или можно подключить через инспектор, кликая мышью — сгенерируется заглушка функции в скрипте. Свои сигналы:
signal health_changed(new_value: int, max_value: int)
func take_damage(amount: int) -> void:
hp -= amount
health_changed.emit(hp, max_hp)
В C#:
[Signal]
public delegate void HealthChangedEventHandler(int newValue, int maxValue);
public void TakeDamage(int amount)
{
_hp -= amount;
EmitSignal(SignalName.HealthChanged, _hp, _maxHp);
}
После Unity-овских UnityEvent.AddListener с их сериализацией сигналы кажутся приятным апгрейдом. Они не теряются при пересборке, нормально работают с тайпчекером и не требуют тащить TextMeshPro-style зависимости.
Физика: похоже, но узлы другие
В Unity ты вешаешь Rigidbody и Collider как компоненты. В Godot физика — это отдельные ноды:
StaticBody2D/3D— статичная геометрия (стены, пол)RigidBody2D/3D— динамика, управляется силамиCharacterBody2D/3D— кинематик с удобнымmove_and_slide()для персонажейArea2D/3D— триггеры, какisTriggerв Unity
Метод move_and_slide — отдельная любовь. В Unity для управляемого персонажа ты пишешь свой контроллер поверх CharacterController или возишься с Rigidbody.MovePosition. В Godot движок даёт готовое решение: задаёшь velocity, вызываешь move_and_slide(), получаешь нормальную работу со склонами, ступеньками и стенами без боли.
Слои коллизий настраиваются в Project Settings → Physics → Layer Names — функционально как в Unity, только UI поудобнее.
UI: Control-ноды и якоря
UGUI-разработчики, готовьтесь: верстать UI в Godot первое время непривычно. Вместо Canvas, RectTransform и якорей у тебя Control-ноды и контейнеры (VBoxContainer, HBoxContainer, GridContainer, MarginContainer). Логика ближе к веб-вёрстке: контейнеры сами раскладывают детей по правилам, а не якорятся к канвасу.
Через неделю это становится приятнее, чем UGUI. UI Toolkit в Unity 6 концептуально пытается прийти к похожей модели через UXML/USS, так что если ты с ним уже работал — переход будет безболезненный.
Что переносится почти без изменений
- Векторная математика.
Vector2/3почти один в один, методы похожие. Разве что в Godot векторы — структуры с публичными полямиx,y,z, и в C# у них свойстваX,Y,Z(CamelCase). - Тайминги.
Tweenв Godot 4 удобнееDOTween:create_tween().tween_property(self, "position", target, 0.5)— и поехали. - Аудио. Концепт шин (
AudioBus) такой же, как Audio Mixer Groups. Параметры читаются и пишутся скриптом без боли. - Шейдеры. Если ты писал ShaderLab/HLSL — Godot Shader Language ощущается как GLSL с приятным препроцессором. Логика та же: вершинный, фрагментный, лайт-функции.
- Логика игры в целом. Стейт-машины, поведение врагов, инвентари — паттерны те же, синтаксис другой.
Что придётся переучивать
- Asset pipeline. Никаких
.meta-файлов и AssetDatabase. Вместо этого.import-файлы рядом с ассетами и кешированный импорт в.godot/imported. Если коммитишь без.gitignore-настройки — получишь мегабайты мусора в репе. - Сборка проекта. Экспорт в Godot — через шаблоны экспорта, которые ты скачиваешь отдельно. Особенно весело первый раз настраивать Android: SDK, NDK, JDK, ключи. Подробнее в доке Godot — там реально всё расписано, но без чтения никак.
- ScriptableObject. Прямого аналога нет. Используется
Resource— это сериализуемый объект, который можно сохранять в.tres. Похоже, но без хукаOnValidateи без удобного редактора массивов. - Менеджеры сцен и переходы. В Unity ты привык к
SceneManager.LoadSceneAsync. В Godot естьget_tree().change_scene_to_file(), но удобный паттерн — держать корневую сцену с autoload-синглтонами и подгружать игровые сцены как поднодов вручную. - Профилирование. Встроенный профайлер Godot слабее Unity Profiler. Для серьёзной работы я подключаюсь к C#-коду через dotTrace или PerfView. На GDScript — встроенным дебаггером + ручными метками
Performance.add_custom_monitor.
Где Godot реально удобнее
Не хочу превращать в холивар, но честно: запуск проекта (godot.exe, открыл, поехал) занимает секунды. Перезагрузка скриптов после правки — мгновенная. Размер билда маленький. Версионирование сцен через .tscn (текстовый формат) — мерж-конфликты решаются руками, в отличие от Unity-овского YAML с гигантскими guid-полями.
Документация в одном месте, на сайте, плюс встроена в редактор: F1 на любом классе — открывается описание прямо там. После Unity-овских поисков по Manual, Scripting Reference, форумам и Reddit это как глоток воды.
Когда не стоит переходить
Если ты делаешь 3D-проект с серьёзными графическими требованиями, Godot 4 пока проигрывает Unity HDRP по визуалу из коробки. Рендерер Forward+ хорош, но экосистема постпроцессинга, terrain'ов и веток типа GPU Instancing-волосы развивается медленнее.
Если проект коммерческий, под мобилки, с интеграциями (реклама, аналитика, IAP, кросс-промо), готовься писать обвязку сам или искать community-плагины. Я в одном пет-проекте под Android неделю настраивал AdMob, в Unity это полчаса.
И если у тебя команда из десяти Unity-разработчиков, не дёргай всех на Godot из-за принципа. Технический долг от смены инструмента съест выгоду на годы вперёд.
Что советую попробовать первым
Возьми пятничный вечер, поставь Godot 4.3, открой шаблон проекта 2D Platformer (он есть в asset library в редакторе), потыкай. Сделай свою маленькую сцену: персонаж бегает, прыгает, собирает монетки, экран с финальным счётом. Уйдёт часа три-четыре, и ты поймёшь, твой это инструмент или нет, лучше любой статьи.
А ещё прочитай главу Best practices в официальной документации — там собраны паттерны от автора движка, и они расходятся с Unity-овскими сильнее, чем кажется. Особенно про composition over inheritance через сцены и про работу с автозагрузками. Сэкономит пару рефакторингов.