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.

Scripting multi-linguaggio

Godot consente abbinare i linguaggi di scripting in base alle proprie esigenze. Ciò significa che un singolo progetto può definire nodi sia in C# sia in GDScript. Questa pagina esaminerà le possibili interazioni tra due nodi scritti in linguaggi diversi.

I due script seguenti serviranno da riferimenti in questa pagina.

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)

Istanziare nodi

Se non si utilizzano nodi dall'albero di scene, probabilmente si vorrà creare istanze di nodi direttamente da codice.

Istanziare nodi C# da GDScript

Usare C# da GDScript non richiede molto lavoro. Una volta caricato (consultare Classi come risorse), lo script si può istanziare con new().

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

Avvertimento

Quando si creano script .cs, è sempre necessario tenere presente che la classe che Godot utilizzerà è quella denominata come il file .cs stesso. Se quella classe non esiste nel file, apparirà il seguente errore: Invalid call. Nonexistent function `new` in base.

Ad esempio, MyCoolNode.cs dovrebbe contenere una classe denominata MyCoolNode.

La classe C# deve derivare una classe Godot, ad esempio GodotObject. Altrimenti, si verificherà lo stesso errore.

È inoltre necessario verificare che il file .cs sia referenziato nel file .csproj del progetto. Se no, si verificherà lo stesso errore.

Istanziare nodi GDScript da C#

Dal lato C#, tutto funziona allo stesso modo. Una volta caricato, il GDScript si può istanziare con GDScript.New().

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

Qui stiamo usando un Object, ma è possibile usare una conversione di tipo come spiegato in Conversione di tipo e casting.

Accesso ai campi

Accedere ai campi C# da GDScript

Accedere ai campi C# da GDScript è semplice, non ci si dovrebbe preoccupare di nulla.

# 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)

Accedere ai campi GDScript da C#

Poiché C# è tipizzato staticamente, accedere a GDScript da C# è un po' più complicato. Sarà necessario usare GodotObject.Get() e GodotObject.Set(). Il primo argomento è il nome del campo a cui si vuole accedere.

// 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"));

Tenere presente che quando si imposta un valore di campo si dovrebbero usare solo i tipi noti al lato GDScript. In sostanza, ci si dovrebbe lavorare con i tipi integrati come descritto in Tipi integrati o con classi che estendono Object.

Chiamata ai metodi

Chiamare metodi C# da GDScript

Ancora una volta, chiamare metodi C# da GDScript dovrebbe essere semplice. Il processo di marshalling farà del suo meglio per convertire gli argomenti pur di corrispondere alle firme delle funzioni. Se ciò non fosse possibile, apparirà il seguente errore: Invalid call. Nonexistent function `FunctionName`.

# 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])

Chiamare metodi GDScript da C#

Per chiamare i metodi GDScript da C# è necessario utilizzare GodotObject.Call(). Il primo argomento è il nome del metodo che si desidera chiamare. Gli argomenti successivi verranno passati a tale metodo.

// 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.

Connessione ai segnali

Connessione ai segnali C# da 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)

Connessione ai segnali GDScript da 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));

Ereditarietà

Un file GDScript potrebbe non ereditare da uno script C#. Allo stesso modo, uno script C# potrebbe non ereditare da un file GDScript. Dovuto a quanto complesso sarebbe da implementare, è improbabile che questa limitazione sia rimossa in futuro. Consultare questo problema su GitHub per ulteriori informazioni.