C# API differences to GDScript

This is a (incomplete) list of API differences between C# and GDScript.

General differences

As explained in the C# basics, C# generally uses PascalCase instead of the snake_case used in GDScript and C++.

Global scope

Global functions and some constants had to be moved to classes, since C# does not allow declaring them in namespaces. Most global constants were moved to their own enums.

Constants

In C#, only primitive types can be constant. For example, the TAU constant is replaced by the Mathf.Tau constant, but the Vector2.RIGHT constant is replaced by the Vector2.Right read-only property. This behaves similarly to a constant, but can't be used in some contexts like switch statements.

Global enum constants were moved to their own enums. For example, ERR_* constants were moved to the Error enum.

Special cases:

GDScript

C#

TYPE_*

Variant.Type enum

OP_*

Variant.Operator enum

Math functions

Math global functions, like abs, acos, asin, atan and atan2, are located under Mathf as Abs, Acos, Asin, Atan and Atan2. The PI constant can be found as Mathf.Pi.

C# also provides static System.Math and System.MathF classes that may contain other useful mathematical operations.

Random functions

Random global functions, like rand_range and rand_seed, are located under GD. Example: GD.RandRange and GD.RandSeed.

Consider using System.Random or, if you need cryptographically strong randomness, System.Security.Cryptography.RandomNumberGenerator.

Other functions

Many other global functions like print and var_to_str are located under GD. Example: GD.Print and GD.VarToStr.

Exceptions:

GDScript

C#

weakref(obj)

Object.WeakRef(obj)

is_instance_valid(obj)

Object.IsInstanceValid(obj)

Tips

Sometimes it can be useful to use the using static directive. This directive allows to access the members and nested types of a class without specifying the class name.

Example:

using static Godot.GD;

public class Test
{
    static Test()
    {
        Print("Hello"); // Instead of GD.Print("Hello");
    }
}

@export annotation

Use the [Export] attribute instead of the GDScript @export annotation. This attribute can also be provided with optional PropertyHint and hintString parameters. Default values can be set by assigning a value.

Example:

using Godot;

public partial class MyNode : Node
{
    [Export]
    private NodePath _nodePath;

    [Export]
    private string _name = "default";

    [Export(PropertyHint.Range, "0,100000,1000,or_greater")]
    private int _income;

    [Export(PropertyHint.File, "*.png,*.jpg")]
    private string _icon;
}

See also: C# Exports.

signal keyword

Use the [Signal] attribute to declare a signal instead of the GDScript signal keyword. This attribute should be used on a delegate, whose name signature will be used to define the signal. The delegate must have the EventHandler suffix, an event will be generated in the class with the same name but without the suffix, use that event's name with EmitSignal.

[Signal]
delegate void MySignalEventHandler(string willSendAString);

See also: C# Signals.

@onready annotation

GDScript has the ability to defer the initialization of a member variable until the ready function is called with @onready (cf. @onready annotation). For example:

@onready var my_label = get_node("MyLabel")

However C# does not have this ability. To achieve the same effect you need to do this.

private Label _myLabel;

public override void _Ready()
{
    _myLabel = GetNode<Label>("MyLabel");
}

Singletons

Singletons are available as static classes rather than using the singleton pattern. This is to make code less verbose than it would be with an Instance property.

Example:

Input.IsActionPressed("ui_down")

However, in some very rare cases this is not enough. For example, you may want to access a member from the base class Godot.Object, like Connect. For such use cases we provide a static property named Singleton that returns the singleton instance. The type of this instance is Godot.Object.

Example:

Input.Singleton.JoyConnectionChanged += Input_JoyConnectionChanged;

String

Use System.String (string). Most of Godot's String methods have an equivalent in System.String or are provided by the StringExtensions class as extension methods.

Example:

string text = "Get up!";
string[] bigrams = text.Bigrams(); // ["Ge", "et", "t ", " u", "up", "p!"]

Strings are immutable in .NET, so all methods that manipulate a string don't modify the original string and return a newly created string with the modifications applied. To avoid creating multiple string allocations consider using a StringBuilder.

List of Godot's String methods and their equivalent in C#:

GDScript

C#

begins_with

string.StartsWith

bigrams

StringExtensions.Bigrams

bin_to_int

StringExtensions.BinToInt

c_escape

StringExtensions.CEscape

c_unescape

StringExtensions.CUnescape

capitalize

StringExtensions.Capitalize

casecmp_to

StringExtensions.CasecmpTo or StringExtensions.CompareTo (Consider using string.Equals or string.Compare)

chr

N/A

contains

string.Contains

count

StringExtensions.Count (Consider using RegEx)

countn

StringExtensions.CountN (Consider using RegEx)

dedent

StringExtensions.Dedent

ends_with

string.EndsWith

find

StringExtensions.Find (Consider using string.IndexOf or string.IndexOfAny)

findn

StringExtensions.FindN (Consider using string.IndexOf or string.IndexOfAny)

format

Use $ string interpolation

get_base_dir

StringExtensions.GetBaseDir

get_basename

StringExtensions.GetBaseName

get_extension

StringExtensions.GetExtension

get_file

StringExtensions.GetFile

get_slice

N/A

get_slice_count

N/A

get_slicec

N/A

hash

StringExtensions.Hash (Consider using object.GetHashCode unless you need to guarantee the same behavior as in GDScript)

hex_to_int

StringExtensions.HexToInt (Consider using int.Parse or long.Parse with System.Globalization.NumberStyles.HexNumber)

humanize_size

N/A

indent

StringExtensions.Indent

insert

string.Insert (Consider using StringBuilder to manipulate strings)

is_absolute_path

StringExtensions.IsAbsolutePath

is_empty

string.IsNullOrEmpty or string.IsNullOrWhiteSpace

is_relative_path

StringExtensions.IsRelativePath

is_subsequence_of

StringExtensions.IsSubsequenceOf

is_subsequence_ofn

StringExtensions.IsSubsequenceOfN

is_valid_filename

StringExtensions.IsValidFileName

is_valid_float

StringExtensions.IsValidFloat (Consider using float.TryParse or double.TryParse)

is_valid_hex_number

StringExtensions.IsValidHexNumber

is_valid_html_color

StringExtensions.IsValidHtmlColor

is_valid_identifier

StringExtensions.IsValidIdentifier

is_valid_int

StringExtensions.IsValidInt (Consider using int.TryParse or long.TryParse)

is_valid_ip_address

StringExtensions.IsValidIPAddress

join

string.Join

json_escape

StringExtensions.JSONEscape

left

StringExtensions.Left (Consider using string.Substring or string.AsSpan)

length

string.Length

lpad

string.PadLeft

lstrip