Scripting multi-langage

Godot vous permet de mélanger les langages de script selon vos besoins. Cela signifie qu'un seul projet peut utiliser des nœuds en C# et en GDScript. Cette page passe en revue les interactions possibles entre deux nœuds écrits dans des langages différents.

Les deux scripts suivants serviront de référence tout le long de cette 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_n_times(msg : String, n : int) -> void:
    for i in range(n):
        print(msg)

Installer des nœuds

Si vous n'utilisez pas de nœuds venant de l'arbre des scène, vous voudrez probablement instancier les nœuds directement depuis le code.

Instanciation des nœuds C# à partir de GDScript

Utiliser un script en C# depuis GDscript ne demande pas énormément de travail. Une fois chargé (see Les classes comme ressources) le script peut être instancié avec 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

Avertissement

Lors de la création de script .cs, vous devriez toujours garder à l'esprit que la classe que Godot va utiliser est celle qui possède le même nom que le fichier .cs . Si cette classe n'existe pas dans le fichier, vous verrez l'erreur suivante : Invalid call. Nonexistent function `new` in base.

Par exemple, MonSuperNoeud.cs devrait contenir une classe nommée MonSuperNoeud.

Vous devez aussi vérifier que votre fichier .cs est référencé dans le fichier projet .csproj. Sinon la même erreur se produira.

Instanciation des nœuds GDScript à partir de C#

Du côté d'un script C#, tout marche de la même manière. Une fois le script écrit en GDscript chargé depuis le script en C#, il peut être instancié avec GDScript.New().

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

Ici, on utilise un Object, mais vous pouvez utiliser la conversion de type tel qu'expliqué dans Conversion de type et Casting.

Accès aux champs

Accès aux champs C# depuis GDScript

Accéder au champ de C# depuis le GDscript est intuitif, vous ne devriez pas rencontrer de problème.

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

Remarquez que cela n'a pas d'importance si un champ est définit comme propriété ou attribut. Mais essayer de changer la valeur d'une propriété qui ne définit pas un setter (une fonction qui change la valeur d'une propriété) résultera en un crash.

Accéder au champ de GDscript depuis du C#

Le C# est typé statiquement, accéder au GDscript depuis C# est plus convoluté.. Il va falloir utiliser Object.Get() et Object.Set(). Le premier argument est le nom du champ que vous souhaitez accéder.

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

Gardez à l'esprit que lorsque vous définissez la valeur d'un champ, vous ne devez utiliser que les types connus du côté GDScript. Essentiellement, vous voulez travailler avec des types intégrés comme décrit dans Bases de GDScript ou des classes héritant de Object.

Méthodes d'appel

Appel de méthodes C# depuis GDScript

Encore une fois, appeler des méthodes C# depuis GDScript devrait être simple. Le processus de sérialisation fera de son mieux pour vous fournir les arguments qui correspondent aux signatures de fonction. Si c'est impossible, vous verrez l'erreur suivante : Invalid call. Nonexistent function `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

Appel de méthodes GDScript depuis C#

Pour appeler des méthodes GDscript depuis C# vous aurez besoin d'utiliser Object.Call(). Le premier argument est le nom de la méthode que vous voulez appeler. Les arguments suivants sont passés à la méthode en question.

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

Avertissement

Comme vous pouvez voir, le premier argument de la méthode appelé est un array, vous aurez besoin de le convertir comme un object. Sinon chaque élément de votre array sera traité comme un argument unique et la signature de la fonction ne correspondra pas.

Héritage

Un fichier GDScript ne peut pas hériter d'un script C#. De même, un script C# ne peut pas hériter d'un fichier GDScript. En effet, la complexité de la mise en œuvre serait telle que cette limitation ne sera surement pas levée à l'avenir. Voir cette édition de GitHub pour plus d'informations.