C# Variant

For a detailed explanation of Variant in general, see theVariant documentation page.

Godot.Variant is used to represent Godot's nativeVariant type. AnyVariant-compatible type can be converted from/to it.We recommend avoidingGodot.Variant unless it is necessary to interact with untyped engine APIs.Take advantage of C#'s type safety when possible.

Converting from a Variant-compatible C# type toGodot.Variant can be done using implicitconversions. There are alsoCreateFrom method overloads and the genericVariant.From<T>methods. Only the syntax is different: the behavior is the same.

intx=42;VariantnumberVariant=x;VarianthelloVariant="Hello, World!";VariantnumberVariant2=Variant.CreateFrom(x);VariantnumberVariant3=Variant.From(x);

Implicit conversions toGodot.Variant make passing variants as method arguments very convenient.For example, the third argument oftween_propertyspecifying the final color of the tween is aGodot.Variant.

Tweentween=CreateTween();tween.TweenProperty(GetNode("Sprite"),"modulate",Colors.Red,1.0f);

Converting fromGodot.Variant to a C# type can be done using explicit conversions. There arealsoVariant.As{TYPE} methods and the genericVariant.As<T> method. All of these behave thesame.

intnumber=(int)numberVariant;stringhello=(string)helloVariant;intnumber2=numberVariant.As<int>();intnumber3=numberVariant.AsInt32();

Note

TheVariant.As{TYPE} methods are typically named after C# types (Int32), not C# keywords(int).

If the Variant type doesn't match the conversion target type, the consequences vary depending on thesource and target values.

  • The conversion may examine the value and return a similar but potentially unexpected value of thetarget type. For example, the string"42a" may be converted to the integer42.

  • The default value of the target type may be returned.

  • An empty array may be returned.

  • An exception may be thrown.

Converting to the correct type avoids complicated behavior and should be preferred.

TheVariant.Obj property returns a C#object with the correct value for any variant. Thismay be useful when the type of Variant is completely unknown. However, when possible, prefer morespecific conversions.Variant.Obj evaluates aswitch onVariant.VariantType and it maynot be necessary. Also, if the result is a value type, it is boxed.

For example, if the potential forVariant.As<MyNode>() to throw an invalid cast exception isn'tacceptable, consider using aVariant.As<GodotObject>()isMyNoden type pattern instead.

Note

Since the Variant type in C# is a struct, it can't be null. To create a "null"Variant, use thedefault keyword or theGodot.Variant parameterless constructor.

Variant-compatible types

A Variant-compatible type can be converted to and from aGodot.Variant.These C# types are Variant-compatible:

  • All thebuilt-in value types,exceptdecimal,nint andnuint.

  • string.

  • Classes derived fromGodotObject.

  • Collections types defined in theGodot.Collections namespace.

Full list of Variant types and their equivalent C# type:

Variant.Type

C# Type

Nil

null (Not a type)

Bool

bool

Int

long (Godot stores 64-bit integers in Variant)

Float

double (Godot stores 64-bit floats in Variant)

String

string

Vector2

Godot.Vector2

Vector2I

Godot.Vector2I

Rect2

Godot.Rect2

Rect2I

Godot.Rect2I

Vector3

Godot.Vector3

Vector3I

Godot.Vector3I

Transform2D

Godot.Transform2D

Vector4

Godot.Vector4

Vector4I

Godot.Vector4I

Plane

Godot.Plane

Quaternion

Godot.Quaternion

Aabb

Godot.Aabb

Basis

Godot.Basis

Transform3D

Godot.Transform3D

Projection

Godot.Projection

Color

Godot.Color

StringName

Godot.StringName

NodePath

Godot.NodePath

Rid

Godot.Rid

Object

Godot.GodotObject or any derived type.

Callable

Godot.Callable

Signal

Godot.Signal

Dictionary

Godot.Collections.Dictionary

Array

Godot.Collections.Array

PackedByteArray

byte[]

PackedInt32Array

int[]

PackedInt64Array

long[]

PackedFloat32Array

float[]

PackedFloat64Array

double[]

PackedStringArray

string[]

PackedVector2Array

Godot.Vector2[]

PackedVector3Array

Godot.Vector3[]

PackedVector4Array

Godot.Vector4[]

PackedColorArray

Godot.Color[]

Warning

Godot uses 64-bit integers and floats in Variant. Smaller integer and float typessuch asint,short andfloat are supported since they can fit in thebigger type. Be aware that when a conversion is performed, using the wrongtype will result in potential precision loss.

Warning

Enums are supported byGodot.Variant since their underlying type is an integertype which are all compatible. However, implicit conversions don't exist, enums mustbe manually converted to their underlying integer type before they can converted to/fromGodot.Variant or use the genericVariant.As<T> andVariant.From<T> methodsto convert them.

enumMyEnum{A,B,C}Variantvariant1=(int)MyEnum.A;MyEnumenum1=(MyEnum)(int)variant1;Variantvariant2=Variant.From(MyEnum.A);MyEnumenum2=variant2.As<MyEnum>();

Using Variant in a generic context

When using generics, you may be interested in restricting the genericT type to beonly one of the Variant-compatible types. This can be achieved using the[MustBeVariant]attribute.

publicvoidMethodThatOnlySupportsVariants<[MustBeVariant]T>(TonlyVariant){// Do something with the Variant-compatible value.}

Combined with the genericVariant.From<T> allows you to obtain an instance ofGodot.Variantfrom an instance of a genericT type. Then it can be used in any API that only supports theGodot.Variant struct.

publicvoidMethod1<[MustBeVariant]T>(TvariantCompatible){Variantvariant=Variant.From(variantCompatible);Method2(variant);}publicvoidMethod2(Variantvariant){// Do something with variant.}

In order to invoke a method with a generic parameter annotated with the[MustBeVariant]attribute, the value must be a Variant-compatible type or a genericT type annotatedwith the[MustBeVariant] attribute as well.

publicclassObjectDerivedClass:GodotObject{}publicclassNonObjectDerivedClass{}publicvoidMain<[MustBeVariant]T1,T2>(T1someGeneric1,T2someGeneric2){MyMethod(42);// Works because `int` is a Variant-compatible type.MyMethod(newObjectDerivedClass());// Works because any type that derives from `GodotObject` is a Variant-compatible type.MyMethod(newNonObjectDerivedClass());// Does NOT work because the type is not Variant-compatible.MyMethod(someGeneric1);// Works because `T1` is annotated with the `[MustBeVariant]` attribute.MyMethod(someGeneric2);// Does NOT work because `T2` is NOT annotated with the `[MustBeVariant]` attribute.}publicvoidMyMethod<[MustBeVariant]T>(Tvariant){// Do something with variant.}

User-contributed notes

Please read theUser-contributed notes policy before submitting a comment.