PONYλM2Modula-2
CodeCompared
for GDScript programmers

You already know GDScript.Now explore other languages.

Side-by-side, interactive cheatsheets for GDScript programmers
comparing GDScript to other languages. Every example runs live in your browser — no setup, no installation.

▶ Start with C#Browse comparisons ↓Explore the language map ↗

Choose your own path by reordering languages

C#Pre-Alpha

Godot's other official language, in the same editor, on the same scene tree. You keep every node, signal and lifecycle callback you already know — _ready becomes _Ready and $Sprite2D becomes GetNode<Sprite2D>("Sprite2D"). What changes is everything around them: types are checked before the game runs, a build step stands between you and pressing play, and the engine's reference counting now has .NET's garbage collector living beside it.

  • Types stop being optional. GDScript lets you write var speed or var speed := 5.0 and checks the annotated one at runtime; C# has no untyped option, and the error arrives at build time instead of on the frame that touches it
  • Truthiness is gone — a condition must be a bool, so if (health) does not compile where if health: quietly meant "not zero"
  • Signals become two things at once: [Signal] delegate void HealthChangedEventHandler(int amount) declares one, and connecting is HealthChanged += OnHealthChanged — a C# event, checked for arity and type at compile time rather than at emit_signal
  • @export var speed := 200.0 becomes [Export] public float Speed = 200.0f; and still appears in the inspector, because the attribute is what the editor reads
  • Two lifetimes now overlap. A Node you QueueFree() is destroyed by the engine while its C# wrapper is collected by the GC, so a disposed node reached through a stale reference throws instead of returning null
  • LINQ replaces the for-loop-into-a-fresh-Array that GDScript makes you write for every filter, map and group
  • await get_tree().create_timer(1.0).timeout is await ToSignal(GetTree().CreateTimer(1.0), "timeout") — the same idea, with the compiler checking that the method returning it is async