Cross-language scripting

Godot permite que você misture e combine linguagens de script para atender às suas necessidades. Isso significa que um único projeto pode definir nós tanto em C# quanto em GDScript. Esta página passará pelas possíveis interações entre dois nós escritos em diferentes linguagens.

The following two scripts will be used as references throughout this page.

extends Node

var str1 : String = "foo"
var str2 : String setget ,get_str2

func get_str2() -> String:
    return "foofoo"

func print_node_name(node : Node) -> void:
    print(node.get_name())

func print_array(arr : Array) -> void:
    for element in arr:
        print(element)

func print_x_times(msg : String, n : int) -> void:
    for i in range(n):
        print(msg)
public class MyCSharpNode : Node
{
    public String str1 = "bar";
    public String str2 { get { return "barbar"; } }

    public void PrintNodeName(Node node)
    {
        GD.Print(node.GetName());
    }

    public void PrintArray(String[] arr)
    {
        foreach (String element in arr)
        {
            GD.Print(element);
        }
    }

    public void PrintNTimes(String msg, int n)
    {
        for (int i = 0; i < n; ++i)
        {
            GD.Print(msg);
        }
    }
}

Instantiating nodes

Se você não estiver usando nós da árvore da cena, provavelmente vai querer instanciar os nós diretamente do código.

Instantiating C# nodes from GDScript

Usar C# a partir do GDScript não precisa de muito trabalho. Uma vez carregado (veja :doc_gdscript_classes_as_resources) o script pode ser instanciado com new().

var my_csharp_script = load("res://path_to_cs_file.cs")
var my_csharp_node = my_csharp_script.new()
print(my_csharp_node.str2) # barbar

Aviso

Ao criar scripts .cs você deve sempre ter em mente que a classe que Godot usará é a nomeada como o próprio arquivo .cs. Se essa classe não existir no arquivo, você verá o seguinte erro: Chamada inválida. Função inexistente 'new' na base.

Por exemplo, MyCoolNode.cs deve conter uma classe chamada MyCoolNode.

Você também precisa verificar se seu arquivo .cs é referenciado no arquivo .csproj do projeto. Caso contrário, o mesmo erro ocorrerá.

Instantiating GDScript nodes from C#

Do lado C#, tudo funciona da mesma maneira. Uma vez carregado, um GDScript pode ser instanciado com GDScript.New().

GDScript MyGDScript = (GDScript) GD.Load("res://path_to_gd_file.gd");
Object myGDScriptNode = (Godot.Object) MyGDScript.New(); // This is a Godot.Object

Aqui estamos usando um class_Object mas você pode usar conversão de tipo como explicado em Type conversion and casting.

Accessing fields

Accessing C# fields from GDScript

Acessar os campos do C# no GDScript é simples, você não deve ter nada com que se preocupar.

print(my_csharp_node.str1) # bar
my_csharp_node.str1 = "BAR"
print(my_csharp_node.str1) # BAR

print(my_csharp_node.str2) # barbar
# my_csharp_node.str2 = "BARBAR" # This line will hang and crash

Observe que não importa se o campo é definido como uma propriedade ou um atributo, mas tentar definir um valor em uma propriedade que não tem um setter resultará em um crash.

Acessando campos do GDScript no C #

Como C# é estáticamente tipado, acessar os campos de GDScript a partir do C# é um pouco mais complicado, você terá que usar Object.Get() e Object.Set(). O primeiro argumento é o nome do campo que você quer acessar.

GD.Print(myGDScriptNode.Get("str1")); // foo
myGDScriptNode.Set("str1", "FOO");
GD.Print(myGDScriptNode.Get("str1")); // FOO

GD.Print(myGDScriptNode.Get("str2")); // foofoo
// myGDScriptNode.Set("str2", "FOOFOO"); // This line won't do anything

Tenha em mente que ao definir um valor de campo você só deve usar tipos conhecidos pelo GDScript. Essencialmente, você precisa trabalhar com tipos embutidos descritos em Básicos do GDScript ou classes que estendam class_Object.

Calling methods

Calling C# methods from GDScript

Novamente, chamar métodos de C# no GDScript deve ser simples. O processo de marshalling fará o seu melhor para converter seu argumento para bater com as assinaturas de funções. Se isso for impossível, você verá o seguinte erro: Chamada inválida. Função inexistente `FunctionName`.

my_csharp_node.PrintNodeName(self) # myGDScriptNode
# my_csharp_node.PrintNodeName() # This line will fail.

my_csharp_node.PrintNTimes("Hello there!", 2) # Hello there! Hello there!

my_csharp_node.PrintArray(["a", "b", "c"]) # a, b, c
my_csharp_node.PrintArray([1, 2, 3]) # 1, 2, 3

Chamando métodos de GDScript no C #

Para chamar os métodos de GDScript a partir do C# você precisará usar Object.Call(). O primeiro argumento é o nome do método que você quer chamar. Os próximos argumentos serão passados para esse método.

myGDScriptNode.Call("print_node_name", this); // my_csharp_node
// myGDScriptNode.Call("print_node_name"); // This line will fail silently and won't error out.

myGDScriptNode.Call("print_n_times", "Hello there!", 2); // Hello there! Hello there!

// When dealing with functions taking a single array as arguments, we need to be careful.
// If we don't cast it into an object, the engine will treat each element of the array as a separate argument and the call will fail.
String[] arr = new String[] { "a", "b", "c" };
// myGDScriptNode.Call("print_array", arr); // This line will fail silently and won't error out.
myGDScriptNode.Call("print_array", (object)arr); // a, b, c
myGDScriptNode.Call("print_array", (object)new int[] { 1, 2, 3 }); // 1, 2, 3
// Note how the type of each array entry does not matter as long as it can be handled by the marshaller

Aviso

Como você pode ver, se o primeiro argumento do método chamado é uma matriz, você precisará converte-la para object. Caso contrário, cada elemento de sua matriz será tratado como um único argumento e a assinatura da função não corresponderá.