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 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_n_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);
}
}
}
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 my_csharp_script = load("res://path_to_cs_file.cs")
var my_csharp_node = my_csharp_script.new()
print(my_csharp_node.str2) # barbar
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".
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().
GDScript MyGDScript = (GDScript) GD.Load("res://path_to_gd_file.gd");
Object myGDScriptNode = (Godot.Object) MyGDScript.New(); // This is a Godot.Object
Aquí usaremos un Object, pero puedes usar conversión de tipos como está explicado en Conversión de tipo y casting.
Accediendo campos¶
Accediendo campos C# desde GDScript¶
Acceder a los campos C# desde GDScript es sencillo, no deberías tener nada de qué preocuparte.
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
Nota que no importa si el campo está definido como propiedad o atributo. Sin embargo, tratar de asignar un valor a una propiedad que no define un setter resultará en un crash.
Accediendo a los campos de GDScript desde C#¶
Como C# es tipado estáticamente, acceder GDScript desde C# es un poco complejo, deberás usar Object.Get() y Object.Set(). El primer argumento es el nombre del campo al que quieres acceder.
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
Ten en cuenta que al establecer un valor de campo sólo debes usar los tipos que el lado GDScript conoce. Esencialmente, quieres trabajar con tipos incorporados como se describe en Bases de GDScript o clases que se extienden 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.
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
Llamando métodos GDScript desde C#¶
Para llamar a los métodos de GDScript desde C# necesitarás usar Object.Call(). El primer argumento es el nombre del método que quieres llamar. Los siguientes argumentos se pasarán a dicho 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
Advertencia
Como puedes ver, si el primer argumento del método llamado es un array, necesitarás lanzarlo como "object". De lo contrario, cada elemento de tu array será tratado como un único argumento y la firma de la función no coincidirá.
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.