Attention: Here be dragons

This is the latest (unstable) version of this documentation, which may document features not available in or compatible with released stable versions of Godot.

C# Variant

For uma explicação detalhada sobre Variant em geral, veja a página de documentação sobre Variant.

Godot.Variant é usado para representar o tipo nativo Variant do Godot. Qualquer tipo compatível com Variant pode ser convertido de/para ele. Recomendamos evitar o uso de Godot.Variant, a menos que seja necessário para interagir com APIs não tipadas do motor. Aproveite a segurança de tipos do C# sempre que possível.

A conversão de um tipo C# compatível com Variant para Godot.Variant pode ser feita usando conversões implícitas. Também existem sobrecargas do método CreateFrom e os métodos genéricos Variant.From<T>. Apenas a sintaxe é diferente: o comportamento é o mesmo.

int x = 42;
Variant numberVariant = x;
Variant helloVariant = "Hello, World!";

Variant numberVariant2 = Variant.CreateFrom(x);
Variant numberVariant3 = Variant.From(x);

As conversões implícitas para Godot.Variant tornam a passagem de variantes como argumentos de método muito conveniente. Por exemplo, o terceiro argumento de tween_property, que especifica a cor final do tween, é um Godot.Variant.

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

A conversão de Godot.Variant para um tipo C# pode ser feita usando conversões explícitas. Também existem os métodos Variant.As{TYPE} e o método genérico Variant.As<T>. Todos eles se comportam da mesma forma.

int number = (int)numberVariant;
string hello = (string)helloVariant;

int number2 = numberVariant.As<int>();
int number3 = numberVariant.AsInt32();

Nota

Os métodos Variant.As{TYPE} geralmente são nomeados com base nos tipos do C# (Int32), e não nas palavras-chave do C# (int).

Se o tipo da Variant não corresponder ao tipo de destino da conversão, as consequências variam dependendo dos valores de origem e de destino.

  • A conversão pode examinar o valor e retornar um valor semelhante, mas potencialmente inesperado, do tipo de destino. Por exemplo, a string "42a" pode ser convertida para o número inteiro 42.

  • O valor padrão do tipo de destino pode ser retornado.

  • Um array vazio pode ser retornado.

  • Uma exceção pode ser lançada.

A conversão para o tipo correto evita comportamentos complicados e deve ser preferida.

A propriedade Variant.Obj retorna um object do C# com o valor correto para qualquer variante. Isso pode ser útil quando o tipo da Variant é totalmente desconhecido. No entanto, quando possível, prefira conversões mais específicas. A propriedade Variant.Obj avalia um switch em Variant.VariantType, o que pode não ser necessário. Além disso, se o resultado for um tipo de valor, ele passará por boxing.

Por exemplo, se a possibilidade de Variant.As<MyNode>() lançar uma exceção de conversão inválida (invalid cast exception) não for aceitável, considere usar o padrão de tipos Variant.As<GodotObject>() is MyNode n em seu lugar.

Nota

Como o tipo Variant no C# é uma struct, ele não pode ser nulo. Para criar uma Variant "nula", use a palavra-chave default ou o construtor sem parâmetros de Godot.Variant.

Tipos compatíveis com Variant

Um tipo compatível com Variant pode ser convertido para e a partir de um Godot.Variant. Estes tipos do C# são compatíveis com Variant:

Lista completa de tipos de Variant e seus tipos equivalentes em C#:

Variant.Type

Tipo C#

Nil

null (Não é um tipo)

Bool

bool

Int

long (O Godot armazena inteiros de 64 bits em Variant)

Float

double (O Godot armazena números de ponto flutuante de 64 bits em 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 ou qualquer tipo derivado.

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[]

Aviso

O Godot usa inteiros e floats de 64 bits em Variant. Tipos menores de inteiros e floats, como int, short e float, são suportados porque cabem no tipo maior. Fique atento ao fato de que, quando uma conversão é realizada, usar o tipo incorreto resultará em uma potencial perda de precisão.

Aviso

Enums são suportados por Godot.Variant, já que seu tipo subjacente é um tipo inteiro, os quais são todos compatíveis. No entanto, não existem conversões implícitas; os enums devem ser convertidos manualmente para seu tipo inteiro subjacente antes de poderem ser convertidos para/de Godot.Variant, ou você pode usar os métodos genéricos Variant.As<T> e Variant.From<T> para convertê-los.

enum MyEnum { A, B, C }

Variant variant1 = (int)MyEnum.A;
MyEnum enum1 = (MyEnum)(int)variant1;

Variant variant2 = Variant.From(MyEnum.A);
MyEnum enum2 = variant2.As<MyEnum>();

Usando Variant em um contexto genérico

Ao usar genéricos, você pode ter interesse em restringir o tipo genérico T para ser apenas um dos tipos compatíveis com Variant. Isso pode ser alcançado usando o atributo [MustBeVariant].

public void MethodThatOnlySupportsVariants<[MustBeVariant] T>(T onlyVariant)
{
    // Do something with the Variant-compatible value.
}

Combinado com o método genérico Variant.From<T>, isso permite que você obtenha uma instância de Godot.Variant a partir de uma instância de um tipo genérico T. Depois, ela pode ser usada em qualquer API que suporte apenas a struct Godot.Variant.

public void Method1<[MustBeVariant] T>(T variantCompatible)
{
    Variant variant = Variant.From(variantCompatible);
    Method2(variant);
}

public void Method2(Variant variant)
{
    // Do something with variant.
}

Para invocar um método com um parâmetro genérico anotado com o atributo [MustBeVariant], o valor deve ser um tipo compatível com Variant ou um tipo genérico T que também esteja anotado com o atributo [MustBeVariant].

public class ObjectDerivedClass : GodotObject { }

public class NonObjectDerivedClass { }

public void Main<[MustBeVariant] T1, T2>(T1 someGeneric1, T2 someGeneric2)
{
    MyMethod(42); // Works because `int` is a Variant-compatible type.
    MyMethod(new ObjectDerivedClass()); // Works because any type that derives from `GodotObject` is a Variant-compatible type.
    MyMethod(new NonObjectDerivedClass()); // 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.
}

public void MyMethod<[MustBeVariant] T>(T variant)
{
    // Do something with variant.
}