Scripting de varios lenguajes

Godot permite mezclar lenguajes de script según tus necesidades. Esto quiere decir que un proyecto puede definir nodos en C# y GDScript. Esta página mostrará las posibles interacciones entre dos nodos escritos en diferentes lenguajes.

Los siguientes dos scripts se utilizarán como referencias a lo largo de esta página.

extends Node

var my_property: String = "my gdscript value":
    get:
        return my_property
    set(value):
        my_property = value

signal my_signal
signal my_signal_with_params(msg: String, n: int)

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_n_times(msg: String, n: int) -> void:
    for i in range(n):
        print(msg)

func my_signal_handler():
    print("The signal handler was called!")

func my_signal_with_params_handler(msg: String, n: int):
    print_n_times(msg, n)

Instanciando nodos

Si no estás usando nodos del árbol de escena, probablemente quieras instanciar nodos directamente desde código.

Instanciando nodos C# desde GDScript

Usar C# de GDScript no necesita mucho trabajo. Una vez cargado (ver Clases como recursos), el script puede ser instanciado con new().

var MyCSharpScript = load("res://Path/To/MyCSharpNode.cs")
var my_csharp_node = MyCSharpScript.new()

Advertencia

Cuando se crea un script .cs, ten siempre en mente que la clase que usará Godot es la que está nombrada como el archivo .cs. Si esa clase no existe en el archivo, verás el siguiente error: Invalid call. Nonexistent function `new` in base.

Por ejemplo, "MyCoolNode.cs"debe contener una clase llamada "MyCoolNode".

The C# class needs to derive a Godot class, for example GodotObject. Otherwise, the same error will occur.

También necesitas revisar que tu archivo .cs esté referenciado en el archivo de proyecto``.csproj``. De otro modo sucederá el mismo error.

Instanciando nodos GDScript desde C#

Desde el lado de C#, todo funciona de la misma manera. Una vez cargado, el GDScript puede ser instanciado con GDScript.New().

var myGDScript = GD.Load<GDScript>("res://path/to/my_gd_script.gd");
var myGDScriptNode = (GodotObject)myGDScript.New(); // This is a GodotObject.

Aquí usaremos un Object, pero puedes usar conversión de tipos como está explicado en Conversión de tipo y casting.

Acceder campos

Acceder campos de C# desde GDScript

Acceder a los campos C# desde GDScript es sencillo, no deberías tener nada de qué preocuparte.

# Output: "my c# value".
print(my_csharp_node.MyProperty)
my_csharp_node.MyProperty = "MY C# VALUE"
# Output: "MY C# VALUE".
print(my_csharp_node.MyProperty)

Acceder a los campos de GDScript desde C#

As C# is statically typed, accessing GDScript from C# is a bit more convoluted. You will have to use GodotObject.Get() and GodotObject.Set(). The first argument is the name of the field you want to access.

// Output: "my gdscript value".
GD.Print(myGDScriptNode.Get("my_property"));
myGDScriptNode.Set("my_property", "MY GDSCRIPT VALUE");
// Output: "MY GDSCRIPT VALUE".
GD.Print(myGDScriptNode.Get("my_property"));

Keep in mind that when setting a field value you should only use types the GDScript side knows about. Essentially, you want to work with built-in types as described in Tipos integrados or classes extending Object.

Llamando métodos

Llamando métodos C# desde GDScript

Una vez más, llamar a métodos C# desde GDScript debería ser sencillo. El proceso de clasificación hará todo lo posible para convertir los argumentos para que coincidan con las firmas de funciones. Si eso es imposible, verá el siguiente error: Llamada no válida. Función `FunctionName` inexistente.

# Output: "my_gd_script_node" (or name of node where this code is placed).
my_csharp_node.PrintNodeName(self)
# This line will fail.
# my_csharp_node.PrintNodeName()

# Outputs "Hello there!" twice, once per line.
my_csharp_node.PrintNTimes("Hello there!", 2)

# Output: "a", "b", "c" (one per line).
my_csharp_node.PrintArray(["a", "b", "c"])
# Output: "1", "2", "3"  (one per line).
my_csharp_node.PrintArray([1, 2, 3])

Llamando métodos GDScript desde C#

To call GDScript methods from C# you'll need to use GodotObject.Call(). The first argument is the name of the method you want to call. The following arguments will be passed to said method.

// Output: "MyCSharpNode" (or name of node where this code is placed).
myGDScriptNode.Call("print_node_name", this);
// This line will fail silently and won't error out.
// myGDScriptNode.Call("print_node_name");

// Outputs "Hello there!" twice, once per line.
myGDScriptNode.Call("print_n_times", "Hello there!", 2);

string[] arr = ["a", "b", "c"];
// Output: "a", "b", "c" (one per line).
myGDScriptNode.Call("print_array", arr);
// Output: "1", "2", "3"  (one per line).
myGDScriptNode.Call("print_array", new int[] { 1, 2, 3 });
// Note how the type of each array entry does not matter
// as long as it can be handled by the marshaller.

Connecting to signals

Connecting to C# signals from GDScript

Connecting to a C# signal from GDScript is the same as connecting to a signal defined in GDScript:

my_csharp_node.MySignal.connect(my_signal_handler)

my_csharp_node.MySignalWithParams.connect(my_signal_with_params_handler)

Connecting to GDScript signals from C#

Connecting to a GDScript signal from C# only works with the Connect method because no C# static types exist for signals defined by GDScript:

myGDScriptNode.Connect("my_signal", Callable.From(MySignalHandler));

myGDScriptNode.Connect("my_signal_with_params", Callable.From<string, int>(MySignalWithParamsHandler));

Herencia

Un archivo GDSCript no puede heredar de un script C# del mismo en que un script C# no puede heredar de un archivo GDScript. Debido a la complejidad que llevaría implementarla, es poco probable que esta limitación sea cambiada en el futuro. Ver esta issue en GitHub para más información.