61 results, 61 expanded

A Godot scene is a tree of typed Nodes; there is no empty container you bolt components onto.

Unity C#
var go = new GameObject("Player");
go.AddComponent<SpriteRenderer>();
Godot 4.7
var player := Node2D.new()
add_child(player)
Pick the most specific node type (Sprite2D, CharacterBody2D) instead of a bare Node.
Godot docs →

A saved scene is Godot's prefab: instance it at runtime or drop it into another scene.

Unity C#
Instantiate(prefab, pos, Quaternion.identity);
Godot 4.7
@export var enemy_scene: PackedScene
var e := enemy_scene.instantiate()
add_child(e)
Godot docs →

Composition happens by adding typed child nodes to the tree, not by attaching components to a container object.

Unity C#
public class Health : MonoBehaviour { public int hp = 100; }
// attached in the Inspector
Godot 4.7
# health.gd attached as a child Node
class_name Health
extends Node
@export var hp: int = 100
Composition is scene-tree composition: nest small single-purpose nodes instead of stacking components on one object.
Godot docs →

Node2D and Node3D each carry position, rotation, and scale directly — there is no separate Transform component to fetch first.

Unity C#
transform.position = new Vector3(0, 5, 0);
transform.Rotate(0, 90, 0);
Godot 4.7
position = Vector3(0, 5, 0)
rotate_y(deg_to_rad(90))
Godot docs →

Use a bare Node for a non-visual container, or Marker2D/Marker3D when you also want the editor gizmo for a reference point.

Unity C#
var anchor = new GameObject("SpawnPoint");
Godot 4.7
# SpawnPoint as a Marker3D child in the scene tree
@onready var spawn_point: Marker3D = $SpawnPoint
Godot docs →

Per-frame logic; use _physics_process for physics-step logic.

Unity C#
void Update() { transform.position += v * Time.deltaTime; }
Godot 4.7
func _process(delta: float) -> void:
    position += v * delta
Godot docs →

_init() runs when the object is constructed, before it enters the scene tree — child nodes and @onready vars aren't ready yet.

Unity C#
void Awake() { instanceId = System.Guid.NewGuid(); }
Godot 4.7
func _init() -> void:
    instance_id = Time.get_ticks_usec()
Child nodes and @onready variables are not available yet inside _init() — do that setup in _ready() instead.
Godot docs →

_ready() fires once a node and all its children have entered the scene tree — the right place for @onready-dependent setup.

Unity C#
void Start() { targetHp = maxHp; }
Godot 4.7
func _ready() -> void:
    target_hp = max_hp
Godot docs →

Runs on the fixed physics tick — put movement, collision, and RigidBody-adjacent code here instead of _process.

Unity C#
void FixedUpdate() { rb.AddForce(Vector3.up * jumpForce); }
Godot 4.7
func _physics_process(delta: float) -> void:
    velocity.y += jump_force * delta
Godot docs →

Fires when the node is removed from the scene tree — the place to disconnect signals or release external resources.

Unity C#
void OnDestroy() { EventBus.OnDied -= HandleDied; }
Godot 4.7
func _exit_tree() -> void:
    EventBus.died.disconnect(_on_died)
Godot docs →

There's no direct enable/disable callback pair; hook tree_entered/tree_exiting for lifecycle, or visibility_changed for show/hide-driven logic.

Unity C#
void OnEnable() { spawner.Register(this); }
void OnDisable() { spawner.Unregister(this); }
Godot 4.7
func _ready() -> void:
    tree_entered.connect(_on_tree_entered)
    tree_exiting.connect(_on_tree_exiting)
Godot docs →

Reference named child nodes directly instead of searching by type at runtime.

Unity C#
var body = GetComponent<Rigidbody2D>();
Godot 4.7
@onready var body: CharacterBody2D = $CharacterBody2D
Godot docs →

await a signal or a scene-tree timer instead of an IEnumerator coroutine.

Unity C#
yield return new WaitForSeconds(1f);
Godot 4.7
await get_tree().create_timer(1.0).timeout
Godot docs →

Declare a signal, emit it, and connect listeners — no manual unsubscribe needed.

Unity C#
public UnityEvent onDied;
onDied.Invoke();
Godot 4.7
signal died
died.emit()
Godot docs →

There's no universal base behavior class — any GDScript file that extends a Node subclass becomes that node's behavior.

Unity C#
public class Player : MonoBehaviour { }
Godot 4.7
class_name Player
extends CharacterBody2D
Godot docs →

Load or @export a PackedScene, call instantiate(), then add_child() it into the tree.

Unity C#
var bullet = Instantiate(bulletPrefab, muzzle.position, Quaternion.identity);
Godot 4.7
var bullet := bullet_scene.instantiate()
bullet.global_position = muzzle.global_position
get_tree().current_scene.add_child(bullet)
Godot docs →

queue_free() frees the node at the end of the current frame; use free() only when you need it gone immediately and know it's safe.

Unity C#
Destroy(gameObject);
Godot 4.7
queue_free()
Godot docs →

SendMessage's stringly-typed broadcast has no direct match — prefer a declared signal, or call a method directly if you hold a reference.

Unity C#
gameObject.SendMessage("TakeDamage", 10);
Godot 4.7
if target.has_method("take_damage"):
    target.take_damage(10)
Godot docs →

One-shot delayed calls use get_tree().create_timer(...).timeout; recurring calls use a Timer node with autostart and wait_time.

Unity C#
Invoke(nameof(Explode), 2f);
Godot 4.7
await get_tree().create_timer(2.0).timeout
explode()
Godot docs →

@export exposes a typed variable to the Inspector and to scene/resource serialization.

Unity C#
[SerializeField] private float moveSpeed = 5f;
Godot 4.7
@export var move_speed: float = 5.0
Godot docs →

Register a script as an Autoload (Project Settings) and it becomes a globally-accessible node singleton — no static-field workaround needed.

Unity C#
public static GameManager Instance;
void Awake() { Instance = this; }
Godot 4.7
# res://autoload/game_manager.gd registered as "GameManager" Autoload
GameManager.score += 10
Godot docs →

Full physics-simulated bodies; apply forces/impulses instead of setting position directly.

Unity C#
rb.AddForce(Vector3.up * force, ForceMode.Impulse);
Godot 4.7
apply_central_impulse(Vector3.UP * force)
Godot docs →

Set the velocity property, then call move_and_slide() — it reads and writes the velocity property itself.

Unity C#
controller.Move(velocity * Time.deltaTime);
Godot 4.7
velocity.y -= gravity * delta
move_and_slide()
move_and_slide() takes no arguments in Godot 4 (unlike Godot 3's move_and_slide(velocity)) — set the velocity property before calling it.
Godot docs →

Connect the body_entered signal on the physics body instead of overriding a collision callback.

Unity C#
void OnCollisionEnter(Collision c) { TakeDamage(c.impulse.magnitude); }
Godot 4.7
func _on_body_entered(body: Node) -> void:
    take_damage(10)
On RigidBody2D/RigidBody3D, body_entered only fires if contact_monitor is set to true AND max_contacts_reported is set to a value greater than 0 (it defaults to 0, meaning nothing is reported).
Godot docs →

Areas are Godot's trigger volumes — connect body_entered or area_entered instead of flagging a collider IsTrigger.

Unity C#
void OnTriggerEnter(Collider other) { if (other.CompareTag("Player")) Collect(); }
Godot 4.7
func _on_body_entered(body: Node2D) -> void:
    if body.is_in_group("player"):
        collect()
Godot docs →

collision_layer declares what a body IS; collision_mask declares what it SCANS for — both are 32-bit flag sets.

Unity C#
if (Physics.Raycast(origin, dir, out hit, 100f, enemyLayerMask)) { }
Godot 4.7
$Area3D.collision_layer = 1 << 3  # this body is on layer 4
$Area3D.collision_mask = 1 << 2   # it scans layer 3 only
Godot docs →

Use a RayCast node for continuous checks, or build a PhysicsRayQueryParameters and call intersect_ray() for one-off queries.

Unity C#
if (Physics.Raycast(origin, dir, out RaycastHit hit, 100f)) { }
Godot 4.7
var query := PhysicsRayQueryParameters3D.create(origin, origin + dir * 100.0)
var hit := get_world_3d().direct_space_state.intersect_ray(query)
Godot docs →

ShapeCast nodes sweep a shape continuously; intersect_shape() does a one-off query with a PhysicsShapeQueryParameters.

Unity C#
Collider[] hits = Physics.OverlapSphere(pos, radius, mask);
Godot 4.7
var params := PhysicsShapeQueryParameters3D.new()
params.shape = SphereShape3D.new()
var hits := get_world_3d().direct_space_state.intersect_shape(params)
Godot docs →

get_vector() combines two axes into a single deadzone-normalized Vector2 in one call.

Unity C#
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
Godot 4.7
var dir := Input.get_vector("move_left", "move_right", "move_up", "move_down")
Godot docs →

True for exactly one frame — the frame the mapped action was pressed.

Unity C#
if (Input.GetButtonDown("Jump")) Jump();
Godot 4.7
if Input.is_action_just_pressed("jump"):
    jump()
Godot docs →

Define named actions in Project Settings -> Input Map, then read them with the Input singleton — no separate asset/context system needed.

Unity C#
playerInput.actions["Jump"].performed += OnJump;
Godot 4.7
# Input Map: action "jump" mapped to Space / gamepad A
if Input.is_action_just_pressed("jump"):
    jump()
Godot docs →

An AnimationTree with a state-machine root replaces the Animator Controller's states and transitions.

Unity C#
animator.SetBool("isRunning", true);
animator.SetTrigger("jump");
Godot 4.7
$AnimationTree["parameters/conditions/is_running"] = true
$AnimationTree["parameters/playback"].travel("jump")
Godot docs →

BlendSpace1D blends along one parameter (e.g. speed); BlendSpace2D blends across two (e.g. move direction).

Unity C#
// Blend Tree node mixing Idle/Walk/Run by a "speed" float
Godot 4.7
$AnimationTree["parameters/Blend/blend_position"] = speed / max_speed
Godot docs →

An AnimationPlayer holds named Animation resources with keyed tracks — play them by name.

Unity C#
animator.Play("Attack");
Godot 4.7
$AnimationPlayer.play("attack")
Godot docs →

An Anim Blueprint's event graph plus state machine maps to an AnimationTree paired with a regular GDScript for logic.

Unreal C++
// Anim Blueprint: AnimGraph blends poses driven by a state machine
Godot 4.7
# AnimationTree node with a State Machine root, driven from a script
$AnimationTree.active = true
Godot docs →

Subclass Resource with @export vars for data-driven, savable assets.

Unity C#
[CreateAssetMenu]
public class WeaponData : ScriptableObject { public int damage; }
Godot 4.7
class_name WeaponData extends Resource
@export var damage: int = 0
Godot docs →

Background-load a resource by path, then poll status and fetch it once ready — no addressable asset groups to configure.

Unity C#
var handle = Addressables.LoadAssetAsync<GameObject>("enemy");
await handle.Task;
Godot 4.7
ResourceLoader.load_threaded_request("res://enemies/goblin.tscn")
# poll later:
if ResourceLoader.load_threaded_get_status("res://enemies/goblin.tscn") == ResourceLoader.THREAD_LOAD_LOADED:
    var scene: PackedScene = ResourceLoader.load_threaded_get("res://enemies/goblin.tscn")
Godot docs →

preload() resolves at parse time (path must be a literal); load() resolves at runtime, like a dynamic Resources.Load call.

Unity C#
var tex = Resources.Load<Texture2D>("icons/sword");
Godot 4.7
var icon := preload("res://icons/sword.png")
# or dynamically:
var tex: Texture2D = load(path)
Godot docs →

StandardMaterial3D exposes the built-in PBR shader's parameters without writing shader code.

Unity C#
renderer.material.SetColor("_Color", Color.red);
Godot 4.7
var mat := StandardMaterial3D.new()
mat.albedo_color = Color.RED
$MeshInstance3D.material_override = mat
Godot docs →

VisualShader gives a node-graph editor like Unreal's Material Editor; ShaderMaterial is what you assign once the graph (or raw shader code) is authored.

Unreal C++
// Material Editor node graph compiled into a Material asset
Godot 4.7
var mat := ShaderMaterial.new()
mat.shader = preload("res://shaders/dissolve.gdshader")
$MeshInstance3D.material_override = mat
Godot docs →

Swaps the entire current scene tree for a new one loaded from a .tscn path.

Unity C#
SceneManager.LoadScene("Level2");
Godot 4.7
get_tree().change_scene_to_file("res://levels/level_2.tscn")
Godot docs →

There's no separate additive-load API — instancing a scene and parenting it into the running tree is inherently additive.

Unity C#
SceneManager.LoadScene("UI_HUD", LoadSceneMode.Additive);
Godot 4.7
var hud := preload("res://ui/hud.tscn").instantiate()
add_child(hud)
Godot docs →

Autoload nodes live outside the current scene and survive scene changes automatically — nothing to mark persistent.

Unity C#
void Awake() { DontDestroyOnLoad(gameObject); }
Godot 4.7
# res://autoload/music_player.gd registered as an Autoload — survives change_scene_to_file()
Godot docs →

A Godot 'scene' can be an entire level, a prefab-like reusable piece, or a single node — Levels map to top-level scenes loaded via change_scene_to_file().

Unreal C++
// A Level asset (.umap) containing placed Actors
Godot 4.7
# levels/forest.tscn -- a scene tree rooted at Node3D holding the level content
Godot docs →

Pick the flavor by dimensionality: plain AudioStreamPlayer for UI/music, 2D or 3D for positional sound.

Unity C#
audioSource.PlayOneShot(explosionClip);
Godot 4.7
$AudioStreamPlayer3D.stream = explosion_sound
$AudioStreamPlayer3D.play()
Godot docs →

If no AudioListener2D/3D is made current, the active Camera acts as the listener; add one explicitly to decouple hearing position from the camera.

Unity C#
// AudioListener component on the Main Camera
Godot 4.7
$AudioListener3D.make_current()
Godot docs →

Annotate a method with @rpc(...) and call it directly — the annotation configures authority, reliability, and call mode.

Unity C#
[ServerRpc] void RequestFireServerRpc() { }
Godot 4.7
@rpc("any_peer", "reliable")
func request_fire() -> void:
    pass
Godot docs →

List properties in a MultiplayerSynchronizer's replication config instead of wrapping each field in a NetworkVariable type.

Unity C#
NetworkVariable<int> health = new NetworkVariable<int>();
Godot 4.7
# MultiplayerSynchronizer node with "health" added to its replication property list
Godot docs →

A MultiplayerSpawner watches a parent node and auto-replicates scenes instanced under it to peers.

Unity C#
networkObject.Spawn();
Godot 4.7
# MultiplayerSpawner configured with spawn_path + spawnable_scenes
$MultiplayerSpawner.spawn(enemy_data)
Godot docs →

Combine a MultiplayerSynchronizer for property replication with @rpc-annotated methods for replicated function calls.

Unreal C++
UPROPERTY(Replicated) int32 Health;
void AMyActor::GetLifetimeReplicatedProps(...) { DOREPLIFETIME(AMyActor, Health); }
Godot 4.7
# MultiplayerSynchronizer replicates `health`; RPCs handle replicated actions
@rpc("authority", "call_local")
func apply_damage(amount: int) -> void:
    health -= amount
Godot docs →

Build UI from Control nodes; a reusable widget is just a saved Control scene, styled with a Theme.

Unity C#
// Canvas + RectTransform anchors in the Inspector
Godot 4.7
# Control scene: VBoxContainer > Label + Button, styled by a Theme resource
Godot docs →

Pausing stops _process/_physics_process on pausable nodes; set a node's process_mode to PROCESS_MODE_ALWAYS to keep it running while paused.

Unity C#
Time.timeScale = 0f;
Godot 4.7
get_tree().paused = true
$PauseMenu.process_mode = Node.PROCESS_MODE_ALWAYS
Godot docs →

_process and _physics_process each receive delta as an argument instead of a global property.

Unity C#
transform.position += velocity * Time.deltaTime;
Godot 4.7
func _process(delta: float) -> void:
    position += velocity * delta
Godot docs →

There's no global 'main camera' singleton — ask the viewport for its current camera, and it can return null.

Unity C#
var screenPoint = Camera.main.WorldToScreenPoint(target.position);
Godot 4.7
var cam := get_viewport().get_camera_3d()
if cam:
    var screen_point := cam.unproject_position(target.global_position)
Godot docs →

print() writes to the Output panel/stdout; print_debug() additionally appends the calling function and line.

Unity C#
Debug.Log($"Score: {score}");
Godot 4.7
print("Score: ", score)
Godot docs →

ConfigFile reads/writes simple section/key/value data to disk — a lightweight PlayerPrefs-style store for small settings and save data.

Unity C#
PlayerPrefs.SetInt("highScore", 1200);
PlayerPrefs.Save();
Godot 4.7
var cfg := ConfigFile.new()
cfg.set_value("scores", "high_score", 1200)
cfg.save("user://save.cfg")
Godot docs →

Groups are Godot's tag system — a node can belong to many groups at once, unlike Unity's single-tag-per-object default.

Unity C#
if (other.CompareTag("Enemy")) { }
Godot 4.7
if body.is_in_group("enemy"):
    pass
Godot docs →

There's no built-in GameMode concept; an Autoload script holding rules and state (turn order, win conditions) fills the same role.

Unreal C++
AGameModeBase* GM = GetWorld()->GetAuthGameMode();
Godot 4.7
# res://autoload/match_rules.gd registered as "MatchRules" Autoload
MatchRules.start_round()
Godot docs →

Godot's Input Map plays the same role as an Enhanced Input Action plus Mapping Context pair, without a separate context-priority stack.

Unreal C++
EnhancedInputComponent->BindAction(JumpAction, ETriggerEvent::Triggered, this, &APlayer::Jump);
Godot 4.7
if Input.is_action_just_pressed("jump"):
    jump()
Godot docs →

`as` performs a safe downcast that returns null on failure; `is` just tests the type without casting.

Unreal C++
AEnemy* Enemy = Cast<AEnemy>(OtherActor);
if (Enemy) { }
Godot 4.7
var enemy := other as Enemy
if enemy:
    pass
# or: if other is Enemy:
Godot docs →

Model row-based data as an array of custom Resource instances (or a Dictionary keyed by id) instead of a DataTable asset plus row struct.

Unreal C++
UDataTable* ItemTable;
FItemRow* Row = ItemTable->FindRow<FItemRow>(RowName, TEXT(""));
Godot 4.7
@export var items: Array[ItemData]  # ItemData extends Resource
func find_item(id: String) -> ItemData:
    return items.filter(func(i): return i.id == id).front()
Godot docs →