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.
Checking the stable version of the documentation...
Référence GDScript
GDScript est un langage de programmation de haut niveau, orienté objet, impératif et typé progressivement conçu pour Godot. Il utilise une syntaxe basée sur l'indentation similaire à des langages comme Python. Son objectif est d'être optimisé et étroitement intégré à Godot, permettant une grande flexibilité pour la création et l'intégration de contenu.
GDScript est entièrement indépendant de Python et n'est pas basé sur lui.
Historique
Note
La documentation sur l'histoire de GDScript a été déplacée dans Questions fréquentes.
Exemple de GDScript
Certaines personnes apprennent plus facilement en regardant la syntaxe. Voici donc un exemple de ce à quoi ressemble GDScript.
# Everything after "#" is a comment.
# A file is a class!
# (optional) icon to show in the editor dialogs:
@icon("res://path/to/optional/icon.svg")
# (optional) class definition:
class_name MyClass
# Inheritance:
extends BaseClass
# Member variables.
var a = 5
var s = "Hello"
var arr = [1, 2, 3]
var dict = {"key": "value", 2: 3}
var other_dict = {key = "value", other_key = 2}
var typed_var: int
var inferred_type := "String"
# Constants.
const ANSWER = 42
const THE_NAME = "Charly"
# Enums.
enum {UNIT_NEUTRAL, UNIT_ENEMY, UNIT_ALLY}
enum Named {THING_1, THING_2, ANOTHER_THING = -1}
# Built-in vector types.
var v2 = Vector2(1, 2)
var v3 = Vector3(1, 2, 3)
# Function, with a default value for the last parameter.
func some_function(param1, param2, param3 = 123):
const local_const = 5
if param1 < local_const:
print(param1)
elif param2 > 5:
print(param2)
else:
print("Fail!")
for i in range(20):
print(i)
while param2 != 0:
param2 -= 1
match param3:
3:
print("param3 is 3!")
_:
print("param3 is not 3!")
var local_var = param1 + 3
return local_var
# Functions override functions with the same name on the base/super class.
# If you still want to call them, use "super":
func something(p1, p2):
super(p1, p2)
# It's also possible to call another function in the super class:
func other_something(p1, p2):
super.something(p1, p2)
# Inner class
class Something:
var a = 10
# Constructor
func _init():
print("Constructed!")
var lv = Something.new()
print(lv.a)
Si vous avez déjà de l’expérience avec des langages à typage statique tels que C, C++ ou C# mais que vous n'avez jamais utilisé un langage à typage dynamique, il vous est conseillé de lire ce tutoriel : GDScript : Une introduction aux langages dynamiques.
Identifiants
Toute chaîne de caractère limitée aux caractères alphabétiques (a à z et A à Z), aux chiffres (0 à 9) et _ est un identifiant potentiel. Les identifiants ne doivent également pas commencer par un chiffre. Les identifiants sont sensibles à la casse. (toto est différent de TOTO).
Les identifiants peuvent également contenir la plupart des caractères Unicode faisant partie de UAX#31. Cela vous permet d'utiliser des noms d'identifiants écrits dans des langues autres que l'anglais. Les caractères Unicode considérés comme « pouvant prêter à confusion » avec les caractères ASCII et les émojis ne sont pas autorisés dans les identifiants.
Mots-clés
Ce qui suit est une liste de mots-clés supportés par le langage. Étant donné que les mots-clés sont des mots (jetons) réservés, ils ne peuvent êtres utilisés comme identifiants. Les opérateurs (comme in, not, and ou or) et les noms des types intégrés énumérés dans les sections suivantes sont également réservés.
Les mots-clés sont définis dans le GDScript tokenizer si vous souhaitez regarder sous le capot.
Mot-clé |
Description |
|---|---|
if |
Voir if/else/elif. |
elif |
Voir if/else/elif. |
else |
Voir if/else/elif. |
for |
Voir for. |
while |
Voir while. |
match |
Voir match. |
when |
Used by pattern guards in |
break |
Quitte l'exécution de la boucle |
continue |
Passe immédiatement à l'itération suivante de la boucle |
pass |
Utilisé lorsqu'une instruction est requise syntaxiquement mais où l’exécution de code est indésirable, comme par exemple, dans une fonction vide. |
return |
Retourne une valeur à partir d'une fonction. |
class |
Définit une classe interne. Voir Inner classes. |
class_name |
Définit le script comme une classe accessible globalement avec le nom spécifié. Voir Registering named classes. |
extends |
Définit quelle classe étendre avec la classe courante. |
is |
Teste si une variable est du type d'une classe donnée, ou si elle est d'un type intégré donnée. |
in |
Teste si une valeur se trouve dans une chaîne, un tableau, une plage, un dictionnaire ou un nœud. Lorsqu'il est utilisé avec |
as |
Convertit la valeur vers un type donné, si cela est possible. |
self |
Réfère à l'instance courante de la classe. Voir self. |
super |
Resolves the scope of the parent method. See Inheritance. |
signal |
Définit un signal. Voir Signals. |
func |
Définit une fonction. Voir Functions. |
static |
Définit une fonction statique ou une variable membre statique. |
const |
Définit une constante. Voir Constants. |
enum |
Définit une énumération. Voir Enums. |
var |
Définit une variable. Voir Variables. |
breakpoint |
Aide pour les points d'arrêt du débogueur. Contrairement aux points d'arrêt créés en cliquant dans la gouttière, |
preload |
Précharge une classe ou une variable. Voir Classes as resources. |
await |
Attend la fin d'un signal ou d'une coroutine. Voir Awaiting signals or coroutines. |
yield |
Utilisé auparavant pour les coroutines. Conservé comme mot-clé pour le temps de la transition. |
assert |
Valide une condition, journalise les erreurs en cas d'échec. Est Ignoré dans les compilations autre que celles de débogages. Voir Assert keyword. |
void |
Utilisé pour indiquer qu'une fonction ne renvoie aucune valeur. |
PI |
Constante PI. |
TAU |
Constante TAU. |
INF |
Constante infinie. Utilisée pour les comparaisons et comme résultat de calculs. |
NAN |
Constante NAN (pas un nombre, Not A Number en anglais). Utilisée comme résultat quand les calculs sont impossibles. |
Opérateurs
Voici la liste des opérateurs pris en charge et leur priorité. Tous les opérateurs binaires sont associatifs à gauche, y compris l'opérateur **. Cela signifie que 2 ** 2 ** 3 est égal à (2 ** 2) ** 3. Utilisez des parenthèses pour spécifier explicitement la priorité dont vous avez besoin, par exemple 2 ** (2 ** 3). L'opérateur ternaire if/else est associatif à droite.
Opérateur |
Description |
|---|---|
|
Regroupement (priorité la plus élevée) Les parenthèses ne sont pas vraiment un opérateur, mais vous permettent de spécifier explicitement la priorité d'une opération. |
|
Abonnement |
|
Référence d'attribut |
|
Appel de fonction |
|
|
x is Nodex is not Node |
Test de type Voir aussi la fonction is_instance_of(). |
|
Puissance Multiplie |
|
Opération bit-à-bit de négation |
+x-x |
Identité / Négation |
x * yx / yx % y |
Multiplication / Division / Reste L'opérateur Remarque : ces opérateurs ont le même comportement qu'en C++, ce qui peut être inattendu pour les utilisateurs venant de Python, JavaScript, etc. Voir une note détaillée après le tableau. |
x + yx - y |
Ajout (ou Concaténation) / Soustraction |
x << yx >> y |
Décalage de bits |
|
Opération ET bit à bit (AND) |
|
Opération OU exclusif bit-à-bit (XOR) |
|
Opération OU bit-à-bit (OR) |
x == yx != yx < yx > yx <= yx >= y |
Comparaison Voir la note détaillée après le tableau. |
x in yx not in y |
Vérification d'inclusion
|
not x!x |
Booléen NON (NOT) et son autre notation non recommandée |
x and yx && y |
Booléen ET (AND) et son autre notation non recommandée |
x or yx || y |
Booléen OU (OR) et son autre notation non recommandée |
|
if / else ternaire |
|
|
x = yx += yx -= yx *= yx /= yx **= yx %= yx &= yx |= yx ^= yx <<= yx >>= y |
Affectation (priorité la plus basse) Vous ne pouvez pas utiliser un opérateur d’affectation à l’intérieur d’une expression. |
Note
Le comportement de certains opérateurs peut différer de ce que vous attendez :
Si les deux opérandes de l'opérateur
/sont de type int, alors la division entière est effectuée au lieu de la division réelle. Par exemple,5 / 2 == 2, et non pas2,5. Si cela n'est pas souhaité, utilisez au moins un float (x / 2.0), Faites une conversion de type (float(x) / y), ou multipliez par1.0(x * 1.0 / y).L'opérateur
%n'est disponible que pour les entiers, pour les flottants, utilisez la fonction fmod().Pour les valeurs négatives, l'opérateur
%etfmod()utilisent la troncature au lieu d'arrondir vers moins l'infini. Cela signifie que le reste a un signe. Si vous avez besoin du reste au sens mathématique du terme, utilisez plutôt les fonctions posmod() et fposmod().Les opérateurs
==et!=permettent parfois de comparer des valeurs de types différents (par exemple,1 == 1.0est vrai), mais dans d'autres cas, ils peuvent provoquer une erreur à l'exécution. Si vous n'êtes pas sûr des types des opérandes, vous pouvez utiliser en toute sécurité la fonction is_same() (mais notez qu'elle est plus stricte concernant les types et les références). Pour comparer des nombres à virgule flottante, utilisez plutôt les fonctions is_equal_approx() et is_zero_approx().
Littéraux
Exemple(s) |
Description |
|
Valeur nulle |
|
Valeurs booléennes |
|
Entier en base 10 (décimal) |
|
Entier base 16 (hexadécimal) |
|
Entier base 2 (binaire) |
|
Nombre à virgule flottante (réel) |
|
Chaines de caractères régulières |
|
Chaînes régulières à triples guillemets |
|
Chaînes de caractères brutes |
|
Chaînes de caractères brutes à triple guillemets |
|
|
|
Il existe également deux constructions qui ressemblent à des littéraux, mais qui n'en sont pas réellement :
Exemple |
Description |
|
Abréviation de |
|
Abréviation de |
Les nombres entiers et les nombres flottants peuvent être séparés par des _ pour les rendre plus lisibles. Les manières suivantes d'écrire les nombres sont toutes valables :
12_345_678 # Equal to 12345678.
3.141_592_7 # Equal to 3.1415927.
0x8080_0000_ffff # Equal to 0x80800000ffff.
0b11_00_11_00 # Equal to 0b11001100.
Les littéraux de chaînes régulières peuvent contenir les séquences d’échappement suivantes :
Séquence d'échappement |
S’étend à |
|
Nouvelle ligne (line feed) |
|
Caractère de tabulation horizontale |
|
Retour chariot |
|
Alerte (bip/cloche) |
|
Effacer |
|
Saut de page (Formfeed) |
|
Caractère de tabulation verticale |
|
Guillemet |
|
Apostrophe |
|
Antislash |
|
Entrée Unicode UTF-16 |
|
Entrée Unicode UTF-32 |
Il existe deux manières de représenter un caractère d'échappement Unicode au delà de 0xFFFF :
en tant que paire de substitution UTF-16
\uXXXX\uXXXX.comme une seule entrée UTF-32
\UXXXXXX.
De plus, l'utilisation de \ suivi d'un caractère de nouvelle ligne à l'intérieur d'une chaîne vous permettra de la continuer sur la ligne suivante, sans insérer de caractère de nouvelle ligne dans la chaîne elle-même.
Une chaîne entourée de guillemets d'un type (par exemple ") peut contenir des guillemets d'un autre type (par exemple ') sans échappement. Les chaînes entre guillemets triples vous permettent d'éviter d'échapper jusqu'à deux guillemets consécutifs du même type (sauf s'ils sont adjacents aux bords de la chaîne).
Les chaînes de caractères brutes encodent toujours la chaîne telle qu'elle apparaît dans le code source. Ceci est particulièrement utile pour les expressions régulières. Une chaîne brute ne traite pas les séquences d'échappement, mais il reconnaît \\ et \" (\') et les remplace par eux-mêmes. Ainsi, une chaîne peut avoir un guillemet qui correspond à celui d'ouverture, mais seulement s'il est précédé d'un antislash.
print("\tchar=\"\\t\"") # Prints ` char="\t"`.
print(r"\tchar=\"\\t\"") # Prints `\tchar=\"\\t\"`.
Note
Certaines chaînes ne peuvent pas être représentées à l'aide de chaînes brutes : vous ne pouvez pas avoir un nombre impair d'antislash à la fin d'une chaîne ou avoir un guillemet d'ouverture sans échappement à l'intérieur de la chaîne. Cependant, en pratique, cela n'a pas d'importance puisque vous pouvez utiliser un type de guillemet différent ou utiliser la concaténation avec une chaîne de caractères régulière.
GDScript prend également en charge le formattage des chaînes de caractères.
Annotations
Annotations are special tokens in GDScript that act as modifiers to an entire script, a declaration, a statement, or a location in the source code. Annotations may affect how the script is treated by the Godot editor and the GDScript compiler.
Chaque annotation commence par le caractère @ et est suivie par un nom. Une description détaillée et un exemple pour chaque annotation peuvent être trouvés dans la référence de classe GDScript.
Par exemple, vous pouvez l'utiliser pour exporter une valeur vers l'éditeur :
@export_range(1, 100, 1, "or_greater")
var ranged_var: int = 50
Pour plus d'informations sur l'exportation de propriétés, consultez les exportations GDScript.
Toute expression constante compatible avec le type d'argument requis par l'annotation peut être transmise comme valeur d'argument d'annotation :
const MAX_SPEED = 120.0
@export_range(0.0, 0.5 * MAX_SPEED)
var initial_speed: float = 0.25 * MAX_SPEED
Les annotations peuvent être écrites une par ligne ou bien toutes sur la même ligne. Elles affectent l'instruction suivante qui n'est pas une annotation. Les annotations peuvent avoir des arguments passés entre parenthèses et séparés par des virgules.
Ces deux façons sont équivalentes :
@annotation_a
@annotation_b
var variable
@annotation_a @annotation_b var variable
L'annotation @onready
Lors de l'utilisation de nœuds, il est très courant de vouloir garder des références à des parties de la scène dans une variable. Comme les scènes ne peuvent être configurées que lors de l'entrée dans l'arbre des scènes actives, les sous-nœuds ne peuvent être obtenus que lorsqu'un appel à Node._ready() est fait.
var my_label
func _ready():
my_label = get_node("MyLabel")
Cela peut devenir un peu fastidieux, surtout lorsque les nœuds et les références externes s'accumulent. Pour cela, GDScript dispose de l'annotation @onready, qui diffère l'initialisation d'une variable membre jusqu'à ce que _ready() soit appelé. Elle peut remplacer le code ci-dessus par une seule ligne :
@onready var my_label = get_node("MyLabel")
Avertissement
L'application de @onready et de toute annotation @export sur la même variable ne fonctionne pas comme prévu. L'annotation @onready entraînera la définition de la valeur par défaut après l'entrée en vigueur de @export et la remplacera :
@export var a = "init_value_a"
@onready @export var b = "init_value_b"
func _init():
prints(a, b) # init_value_a <null>
func _notification(what):
if what == NOTIFICATION_SCENE_INSTANTIATED:
prints(a, b) # exported_value_a exported_value_b
func _ready():
prints(a, b) # exported_value_a init_value_b
Par conséquent, l'avertissement ONREADY_WITH_EXPORT est généré et traité comme une erreur par défaut. Nous vous déconseillons de le désactiver ou de l'ignorer.
Régions de code
Les régions de code sont des commentaires spéciaux que l'éditeur de scripts considère comme des régions pliables. Cela signifie qu'après avoir écrit des commentaires de région de code, vous pouvez réduire et développer la région en cliquant sur la flèche qui apparaît à gauche du commentaire. Cette flèche apparaît dans un carré violet pour se distinguer du pliage de code standard.
La syntaxe est la suivante :
# Important: There must be *no* space between the `#` and `region` or `endregion`.
# Region without a description:
#region
...
#endregion
# Region with a description:
#region Some description that is displayed even when collapsed
...
#endregion
Astuce
Pour créer rapidement une région de code, sélectionnez plusieurs lignes dans l'éditeur de script, faites un clic droit sur la sélection puis choisissez Créer une région de code. La description de la région sera automatiquement sélectionnée pour être modifiée.
Il est possible d'imbriquer des régions de code dans d'autres régions de code.
Voici un exemple concret d’utilisation des régions de code :
# This comment is outside the code region. It will be visible when collapsed.
#region Terrain generation
# This comment is inside the code region. It won't be visible when collapsed.
func generate_lakes():
pass
func generate_hills():
pass
#endregion
#region Terrain population
func place_vegetation():
pass
func place_roads():
pass
#endregion
Cela peut être utile pour organiser de gros morceaux de code en sections plus faciles à comprendre. Cependant, n'oubliez pas que les éditeurs externes ne prennent généralement pas en charge cette fonctionnalité. Assurez-vous donc que votre code est facile à suivre, même lorsque vous ne vous appuyez pas sur des zones de code pliables.
Note
Individual functions and indented sections (such as if and for) can
always be collapsed in the script editor. This means you should avoid
using a code region to contain a single function or indented section, as it
won't bring much of a benefit. Code regions work best when they're used to
group multiple elements together.
Continuation de la ligne
Une ligne de code dans GDScript peut être continuée sur la ligne suivante en utilisant un antislash (barre oblique inverse) (\). Ajoutez-en une à la fin d'une ligne et le code de la ligne suivante agira comme s'il s'agissait d'une continuation de la ligne précéndente. Voici un exemple :
var a = 1 + \
2
Une ligne peut être continuée plusieurs fois comme ceci :
var a = 1 + \
4 + \
10 + \
4
Types intégrés
Les types intégrés sont alloués sur la pile. Ils sont transmis comme valeurs. Cela signifie qu'une copie est créée à chaque affectation ou lors de leur transmission comme arguments aux fonctions. Les exceptions sont Object, Array, Dictionary et les tableaux compacts (tels que PackedByteArray), qui sont passés par référence afin d'être partagés. Tous les tableaux, Dictionary et certains objets (Node, Resource) ont une méthode duplicate() qui vous permet d'en faire une copie.
Types intégrés basiques
Une variable dans GDScript peut être affectée à plusieurs types intégrés.
null
null est une donnée vide qui ne contient aucune information et à laquelle aucune autre valeur ne peut être affectée.
Only types that inherit from Object can have a null value
(Object is therefore called a "nullable" type).
Variant types must have a valid value at all times,
and therefore cannot have a null value.
bool
Abréviation de "booléen", il ne peut contenir que true ou false.
int
De l'anglais "integer", il contient des nombres entiers (positifs et négatifs). Ceux-ci sont stockés sous forme de valeurs 64-bits, équivalent à int64_t en C++.
float
Contient un nombre réel (avec décimales), en tant que valeur à virgule flottante. Celui-ci est stocké comme valeur 64 bits, équivalent à double en C++. Note : Actuellement, les structures de données comme Vector2, Vector3 et PackedFloat32Array stockent des valeurs 32 bits à virgules flottantes de précision unique (float).
String
Une séquence de caractères au format Unicode.
StringName
Une chaîne immuable qui n'autorise qu'une seule instance de chaque nom. Elles sont plus lentes à créer et peuvent entraîner l'attente de verrous lors du multi tâche. En échange, elles sont très rapides à comparer, ce qui en fait de bons candidats pour les clés de dictionnaire.
NodePath
Un chemin pré-analysé vers un nœud ou une propriété de nœud. Il peut être facilement assigné à et depuis une chaîne. Ils sont utiles pour interagir avec l'arbre afin d'obtenir un nœud ou d'affecter des propriétés comme avec Tweens.
Types intégrés vectoriels
Vector2
Type de vecteur 2D contenant les propriétés x et y. Peut aussi être accédé de la même façon qu'un tableau.
Vector2i
Identique à Vector2 mais les composants sont des entiers. Utile pour représenter des éléments dans une grille 2D.
Rect2
Type de rectangle 2D contenant deux propriétés de type vecteur : position et size. Contient également une propriété end qui correspond à position + size.
Vector3
Type de vecteur 3D contenant les propriétés x, y et z. Il peut également être accédé de la même façon qu'un tableau.
Vector3i
Identique à Vector3 mais les composants sont des entiers. Peut être utilisé pour indexer des éléments dans une grille 3D.
Transform2D
Matrice 3x2 utilisée pour les transformations 2D.
Plane
Plan 3D normalisé contenant un vecteur normal et une distance scalaire d.
Quaternion
Un quaternion est un type de données utilisé pour représenter une rotation 3D. Cette représentation est utile pour l'interpolation de rotations.
AABB
La boîte englobante (ou boîte 3D) alignée par axe contient 2 propriétés de type vecteur : position et size. Contient également une propriété end qui correspond à position + size.
Basis
Matrice 3x3 utilisée pour les rotations 3D et les mises à l'échelle. Elle contient 3 propriétés de type vecteur (x, y et z) et peut aussi être accédé comme un tableau de vecteurs 3D.
Transform3D
Transformation 3D contenant une propriété de type Basis basis et une propriété vecteur 3D (Vector3) origin.
Types intégrés dans le moteur
Color
Le type de données Color contient les propriétés r, g, b, et a. Il peut aussi être accédé par h, s, et v pour la teinte(hue)/saturation/valeur.
RID
Identifiant de ressource (RID). Les serveurs utilisent des RIDs génériques pour référencer des données opaques.
Object
Classe de base pour tout ce qui n'est pas un type intégré.
Types de conteneurs intégrés
Array
Séquence générique de types d'objets arbitraires, y compris d'autres tableaux ou dictionnaires (voir ci-dessous). Le tableau peut être redimensionné dynamiquement. Les tableaux sont indexés à partir de l'indice 0. Les indices négatifs comptent à partir de la fin.
var arr = []
arr = [1, 2, 3]
var b = arr[1] # This is 2.
var c = arr[arr.size() - 1] # This is 3.
var d = arr[-1] # Same as the previous line, but shorter.
arr[0] = "Hi!" # Replacing value 1 with "Hi!".
arr.append(4) # Array is now ["Hi!", 2, 3, 4].
Tableaux typés
Godot also features support for typed arrays. On write operations, Godot checks that
element values match the specified type, so the array cannot contain invalid values.
The GDScript static analyzer takes typed arrays into account, however array methods like
front() and back() still have the Variant return type.
Les tableaux typés ont la syntaxe Array[Type], où Type peut être n'importe quel type Variant, classe native ou utilisateur, ou énumération. Les types de tableaux imbriqués (comme Array[Array[int]]) ne sont pas pris en charge.
var a: Array[int]
var b: Array[Node]
var c: Array[MyClass]
var d: Array[MyEnum]
var e: Array[Variant]
Array et Array[Variant] sont la même chose.
Note
Les tableaux sont transmis par référence, de sorte que le type d'élément du tableau est également un attribut de la structure en mémoire référencée par une variable lors de l'exécution. Le type statique d'une variable restreint les structures auxquelles elle peut faire référence. Par conséquent, vous ne pouvez pas attribuer un tableau avec un type d'élément différent, même si le type est un sous-type du type requis.
Si vous souhaitez convertir un tableau typé, vous pouvez créer un nouveau tableau et utiliser la méthode Array.assign() :
var a: Array[Node2D] = [Node2D.new()]
# (OK) You can add the value to the array because `Node2D` extends `Node`.
var b: Array[Node] = [a[0]]
# (Error) You cannot assign an `Array[Node2D]` to an `Array[Node]` variable.
b = a
# (OK) But you can use the `assign()` method instead. Unlike the `=` operator,
# the `assign()` method copies the contents of the array, not the reference.
b.assign(a)
Une seule exception a été faite pour le type Array (Array[Variant]), pour des raisons de commodité pour l'utilisateur et de compatibilité avec l'ancien code. Cependant, les opérations sur des tableaux non typés sont considérées comme dangereuses.
Tableaux compacts
PackedArrays are generally faster to iterate on and modify compared to a typed Array of the same type (e.g. PackedInt64Array versus Array[int]) and consume less memory. In the worst case, they are expected to be as fast as an untyped Array. Conversely, non-Packed Arrays (typed or not) have extra convenience methods such as Array.map that PackedArrays lack. Consult the class reference for details on the methods available. Typed Arrays are generally faster to iterate on and modify than untyped Arrays.
Bien que tous les Arrays peuvent causer de la fragmentation de la mémoire lorsqu'ils deviennent assez grands, si l'utilisation de la mémoire et la performance (vitesse d'itération et de modification) est une préoccupation et le type de données que vous stockez est compatible avec l'un des type de tableau Packed, l'utilisation de ceux-ci peuvent produire des améliorations. Cependant, si vous n'avez pas de telles préoccupations (par exemple, la taille de votre tableau n'atteint pas les dizaines de milliers d'éléments), il est probablement plus utile d'utiliser des Arrays réguliers ou typés, car ils fournissent des méthodes de commodité qui peuvent rendre votre code plus facile à écrire et à entretenir (et potentiellement plus rapide si vos données exigent beaucoup de telles opérations). Si les données que vous stockerez sont d'un type connu (y compris vos propres classes définies), préférez utiliser un Array typé car il peut produire une meilleure performance en itération et modification par rapport à un Array non typé.
PackedByteArray: Un tableau d'octets (entiers de 0 à 255).
PackedInt32Array: Un tableau d'entiers 32 bits.
PackedInt64Array: Un tableau d'entiers 64 bits.
PackedFloat32Array: un tableau de nombres flottants 32 bits.
PackedFloat64Array: un tableau de flottants 64 bits.
PackedStringArray: Un tableau de chaînes de caractères.
PackedVector2Array : Un tableau d'objets Vector2.
PackedVector3Array : Un tableau d'objets Vector3.
PackedVector4Array : Un tableau de valeurs Vector4.
PackedColorArray: Un tableau de valeurs de Color.
Dictionary
Conteneur associatif qui contient des valeurs référencées par des clés uniques.
var d = {4: 5, "A key": "A value", 28: [1, 2, 3]}
d["Hi!"] = 0
d = {
22: "value",
"some_key": 2,
"other_key": [2, 3, 4],
"more_key": "Hello"
}
La syntaxe de tableau de style Lua est également prise en charge. Le style Lua utilise = au lieu de : et n'utilise pas de guillemets pour marquer les clés de chaîne (ce qui réduit légèrement la quantité à écrire). Cependant, les clés écrites sous cette forme ne peuvent pas commencer par un chiffre (comme tout identifiant GDScript) et doivent être des chaînes de caractères.
var d = {
test22 = "value",
some_key = 2,
other_key = [2, 3, 4],
more_key = "Hello"
}
Pour ajouter une clé à un dictionnaire existant, accédez-y comme une clé existante et affectez lui une valeur :
var d = {} # Create an empty Dictionary.
d.waiting = 14 # Add String "waiting" as a key and assign the value 14 to it.
d[4] = "hello" # Add integer 4 as a key and assign the String "hello" as its value.
d["Godot"] = 3.01 # Add String "Godot" as a key and assign the value 3.01 to it.
var test = 4
# Prints "hello" by indexing the dictionary with a dynamic key.
# This is not the same as `d.test`. The bracket syntax equivalent to
# `d.test` is `d["test"]`.
print(d[test])
Note
La syntaxe des crochets peut être utilisée pour accéder aux propriétés de n'importe quel Object, et pas seulement aux Dictionnaires. N'oubliez pas qu'elle provoquera une erreur de script lorsque vous tenterez d'indexer une propriété inexistante. Pour éviter cela, utilisez les méthodes Object.get() et Object.set() à la place.
Typed dictionaries
Godot 4.4 added support for typed dictionaries. On write operations, Godot checks that
element keys and values match the specified type, so the dictionary cannot contain invalid
keys or values. The GDScript static analyzer takes typed dictionaries into account. However,
dictionary methods that return values still have the Variant return type.
Typed dictionaries have the syntax Dictionary[KeyType, ValueType], where KeyType and ValueType
can be any Variant type, native or user class, or enum. Both the key and value type must be specified,
but you can use Variant to make either of them untyped.
Nested typed collections (like Dictionary[String, Dictionary[String, int]])
are not supported.
var a: Dictionary[String, int]
var b: Dictionary[String, Node]
var c: Dictionary[Vector2i, MyClass]
var d: Dictionary[MyEnum, float]
# String keys, values can be any type.
var e: Dictionary[String, Variant]
# Keys can be any type, boolean values.
var f: Dictionary[Variant, bool]
Dictionary and Dictionary[Variant, Variant] are the same thing.
Signal
Un signal est un message qui peut être émis par un objet à destination de ceux qui souhaitent l'écouter. Le type Signal peut être utilisé pour faire passer l'émetteur.
Les signaux sont mieux utilisés en les obtenant à partir d'objets réels, par exemple $Button.button_up.
Callable
Contient un objet et une fonction, ce qui est pratique pour transmettre des fonctions en tant que valeurs (par exemple lors de la connexion à des signaux).
Obtenir une méthode en tant que membre renvoie un callable. var x = $Sprite2D.rotate définira la valeur de x sur un callable avec $Sprite2D comme objet et rotate comme méthode.
Vous pouvez l'appeler en utilisant la méthode call : x.call(PI).
Variables
Les variables peuvent exister en tant que membres de la classe ou locales aux fonctions. Elles sont créées avec le mot-clé var et peuvent, éventuellement, se voir attribuer une valeur à l'initialisation.
var a # Data type is 'null' by default.
var b = 5
var c = 3.8
var d = b + c # Variables are always initialized in direct order (see below).
Les variables peuvent optionnellement avoir une spécification de type. Lorsqu'un type est spécifié, la variable sera obligée d'avoir toujours le même type, et essayer d'assigner une valeur incompatible entraînera une erreur.
Les types sont spécifiés dans la variable par un : après le nom de la variable, suivi par le type.
var my_vector2: Vector2
var my_node: Node = Sprite2D.new()
Si la variable est initialisée dans la déclaration, le type peut être déduit, il est donc possible de ne pas mettre le nom du type :
var my_vector2 := Vector2() # 'my_vector2' is of type 'Vector2'.
var my_node := Sprite2D.new() # 'my_node' is of type 'Sprite2D'.
L'inférence de type n'est possible que si la valeur affectée a un type défini, sinon une erreur sera générée.
Les types valides sont :
Types intégrés (Array, Vector2, int, String, etc.).
Engine classes (Node, Resource, RefCounted, etc.).
Les noms des constantes s'ils contiennent un script ressource (
MyScriptsi vous avez déclaréconst MyScript = preload("res://my_script.gd")).D'autres classes dans le même script, respectant la portée (
InnerClass.NestedClasssi vous avez déclaréclass NestedClassà l'intérieur declass InnerClassdans la même portée).Les classes de script déclarées avec le mot-clé
class_name.Chargements automatiques enregistrés comme des singletons.
Note
Bien que Variant soit une spécification de type valide, ce n'est pas un vrai type. Cela signifie simplement qu'il n'y a pas de type défini et cela équivaut à ne pas avoir de type statique du tout. Par conséquent, l'inférence n'est pas autorisée par défaut pour Variant, car il s'agit probablement d'une erreur.
Vous pouvez désactiver cette vérification, ou la transformer simplement en avertissement, en la modifiant dans les paramètres du projet. Voir Système d’avertissement de GDScript pour plus de détails.
Ordre d'initialisation
Les variables membres sont initialisées dans l'ordre suivant :
Selon le type statique de la variable, la variable est soit
null(variables et objets non typés) ou a une valeur par défaut du type (0pourint,falsepourbool, etc.).Les valeurs spécifiées sont attribuées dans l'ordre des variables dans le script, de haut en bas.
(Uniquement pour les classes dérivées de
Node) Si l'annotation@onreadyest appliquée à une variable, son initialisation est reportée à l'étape 5.
Si elle est implémentée, la méthode
_init()est appelée.Lors de l'instanciation de scènes et de ressources, les valeurs exportées sont attribuées.
(Uniquement pour les classes dérivées de
Node) Les variables@onreadysont initialisées.(Uniquement pour les classes dérivées de
Node) Si elle est implémentée, la méthode_ready()est appelée.
Avertissement
Vous pouvez spécifier une expression complexe pour initialiser une variable, y compris des appels de fonction. Assurez-vous que les variables sont initialisées dans le bon ordre, sinon vos valeurs risquent d'être écrasées. Par exemple :
var a: int = proxy("a", 1)
var b: int = proxy("b", 2)
var _data: Dictionary = {}
func proxy(key: String, value: int):
_data[key] = value
print(_data)
return value
func _init() -> void:
print(_data)
Will print:
{ "a": 1 }
{ "a": 1, "b": 2 }
{ }
Pour le corriger, déplacez la définition de la variable _data au-dessus de la définition a ou supprimez l'affectation de dictionnaire vide (= {}).
Variables statiques
A class member variable can be declared static:
static var a
Les variables statiques appartiennent à la classe, pas aux instances. Cela signifie que les variables statiques partagent des valeurs entre plusieurs instances, contrairement aux variables membres classiques.
Depuis l'intérieur d'une classe, vous pouvez accéder aux variables statiques de n'importe quelle fonction, statique ou non. Depuis l'extérieur de la classe, vous pouvez accéder aux variables statiques en utilisant la classe ou une instance (la seconde n'est pas recommandée car elle est moins lisible).
Note
Les annotations @export et @onready ne peuvent pas être appliquées à une variable statique. Les variables locales ne peuvent pas être statiques.
L'exemple suivant définit une classe Person avec une variable statique nommée max_id. Nous incrémentons le max_id dans la fonction _init(). Cela permet de suivre facilement le nombre d'instances Person dans notre jeu.
# person.gd
class_name Person
static var max_id = 0
var id
var name
func _init(p_name):
max_id += 1
id = max_id
name = p_name
Dans ce code, nous créons deux instances de notre classe Person et vérifions que la classe et chaque instance ont la même valeur max_id, car la variable est statique et accessible à chaque instance.
# test.gd
extends Node
func _ready():
var person1 = Person.new("John Doe")
var person2 = Person.new("Jane Doe")
print(person1.id) # 1
print(person2.id) # 2
print(Person.max_id) # 2
print(person1.max_id) # 2
print(person2.max_id) # 2
Les variables statiques peuvent avoir des indices de type, des setters et des getters :
static var balance: int = 0
static var debt: int:
get:
return -balance
set(value):
balance = -value
Une variable statique de classe parente est également accessible via une classe enfant :
class A:
static var x = 1
class B extends A:
pass
func _ready():
prints(A.x, B.x) # 1 1
A.x = 2
prints(A.x, B.x) # 2 2
B.x = 3
prints(A.x, B.x) # 3 3
Note
When referencing a static variable from a tool script, the other script containing the static variable must also be a tool script. See Running code in the editor for details.
Annotation @static_unload
Les classes GDScript étant des ressources, la présence de variables statiques dans un script empêche son déchargement même s'il n'y a plus d'instances de cette classe et aucune autre référence restante. Cela peut être important si les variables statiques stockent de grandes quantités de données ou contiennent des références à d'autres ressources du projet, telles que des scènes. Vous devez nettoyer ces données manuellement ou utiliser l'annotation @static_unload si les variables statiques ne stockent pas de données importantes et peuvent être réinitialisées.
Avertissement
Actuellement, en raison d'un bug, les scripts ne sont jamais libérés, même si l'annotation @static_unload est utilisée.
Notez que @static_unload s'applique à l'ensemble du script (y compris les classes internes) et doit être placé en haut du script, avant class_name et extends :
@static_unload
class_name MyNode
extends Node
Voir aussi Static functions et Static constructor.
Conversion de type
Les valeurs affectées à des variables typées doivent avoir un type compatible. S'il est nécessaire de contraindre une valeur à être d'un certain type, surtout pour les types d'objet, vous pouvez utiliser l'opérateur de conversion as.
La conversion de types d'objets résulte en le même objet si la valeur est du même type ou d'un type enfant du type de conversion.
var my_node2D: Node2D
my_node2D = $Sprite2D as Node2D # Works since Sprite2D is a subtype of Node2D.
Si la valeur n'est pas un type enfant, l'opération de conversion se résultera en une valeur null.
var my_node2D: Node2D
my_node2D = $Button as Node2D # Results in 'null' since a Button is not a subtype of Node2D.
Pour les types intégrés, ils seront convertis de force si possible, sinon le moteur générera une erreur.
var my_int: int
my_int = "123" as int # The string can be converted to int.
my_int = Vector2() as int # A Vector2 can't be converted to int, this will cause an error.
Casting is also useful to have better type-safe variables when interacting with the scene tree:
# Will infer the variable to be of type Sprite2D.
var my_sprite := $Character as Sprite2D
# Will fail if $AnimPlayer is not an AnimationPlayer, even if it has the method 'play()'.
($AnimPlayer as AnimationPlayer).play("walk")
Constantes
Les constantes sont des valeurs que vous ne pouvez pas changer lorsque le jeu est s’exécute. Leur valeur doit être connue au moment de la compilation. L'utilisation du mot-clé const permet de donner un nom à une valeur constante. Si vous essayez d'attribuer une valeur à une constante après qu'elle ait été déclarée, vous obtiendrez une erreur.
Nous recommandons d'utiliser des constantes chaque fois qu'une valeur n'est pas censée changer.
const A = 5
const B = Vector2(20, 20)
const C = 10 + 20 # Constant expression.
const D = Vector2(20, 30).x # Constant expression: 20.
const E = [1, 2, 3, 4][0] # Constant expression: 1.
const F = sin(20) # 'sin()' can be used in constant expressions.
const G = x + 20 # Invalid; this is not a constant expression!
const H = A + 20 # Constant expression: 25 (`A` is a constant).
Although the type of constants is inferred from the assigned value, it's also possible to add explicit type specification:
const A: int = 5
const B: Vector2 = Vector2()
Assigner une valeur à un type incompatible va générer une erreur.
Vous pouvez également créer des constantes à l'intérieur d'une fonction, ce qui est utile pour nommer des valeurs magiques locales.
Énumérations
Les énumérations sont en fait une forme abrégée pour déclarer des constantes, et sont pratiques si vous voulez assigner des entiers consécutifs à certaines constantes.
enum {TILE_BRICK, TILE_FLOOR, TILE_SPIKE, TILE_TELEPORT}
# Is the same as:
const TILE_BRICK = 0
const TILE_FLOOR = 1
const TILE_SPIKE = 2
const TILE_TELEPORT = 3
If you pass a name to the enum, it will put all the keys inside a constant Dictionary of that name. This means all constant methods of a dictionary can also be used with a named enum. This only works for GDScript enums, not for enums from built-in classes.
Important
Les clés d'une énumération nommée ne sont pas enregistrées comme constantes globales. Elles doivent être accessibles en préfixant le nom de l'énumération (Name.KEY).
enum State {STATE_IDLE, STATE_JUMP = 5, STATE_SHOOT}
# Is the same as:
const State = {STATE_IDLE = 0, STATE_JUMP = 5, STATE_SHOOT = 6}
# Access values with State.STATE_IDLE, etc.
func _ready():
# Access values with Name.KEY, prints '5'
print(State.STATE_JUMP)
# Use dictionary methods:
# prints '["STATE_IDLE", "STATE_JUMP", "STATE_SHOOT"]'
print(State.keys())
# prints '{ "STATE_IDLE": 0, "STATE_JUMP": 5, "STATE_SHOOT": 6 }'
print(State)
# prints '[0, 5, 6]'
print(State.values())
If not assigning a value to a key of an enum it will be assigned the previous value plus one,
or 0 if it is the first entry in the enum. Multiple keys with the same value are allowed.
Fonctions
Les fonctions appartiennent toujours à une classe. La priorité de portée pour la recherche de la variable est : locale → membre de classe → globale. La variable self est toujours disponible et est fournie comme option pour accéder aux membres de la classe (voir self), mais n'est pas toujours nécessaire (et ne devrait pas être donnée comme premier argument de la fonction, contrairement au Python).
func my_function(a, b):
print(a)
print(b)
return a + b # Return is optional; without it 'null' is returned.
Une fonction peut return à tout moment. La valeur de retour par défaut est null.
By default, all function parameters are required. You can make one or more parameters at the end optional by assigning a default value to them:
# Since the last two parameters are optional, all these calls are valid:
# - my_function(1)
# - my_function(1, 20)
# - my_function(1, 20, 100)
func my_function(a_required, b_optional = 10, c_optional = 42):
print(a_required)
print(b_optional)
print(c_optional)
If a function contains only one line of code, it can be written on one line:
func square(a): return a * a
func hello_world(): print("Hello World")
func empty_function(): pass
Functions can also have type specification for the arguments and for the return value. Types for arguments can be added in a similar way to variables:
func my_function(a: int, b: String):
pass
If a function argument has a default value, it's possible to infer the type:
func my_function(int_arg := 42, String_arg := "string"):
pass
The return type of the function can be specified after the arguments list using
the arrow token (->):
func my_int_function() -> int:
return 0
Les fonctions qui ont un type de retour doivent retourner une valeur appropriée. Paramétrer le type d'une fonction à void signifie qu'elle ne retournera rien. Les fonctions vides peuvent retourner à l'avance en utilisant le mot-clé return, mais elles ne peuvent pas retourner de valeurs.
func void_function() -> void:
return # Can't return a value.
Note
Les fonctions non-vides doivent toujours retourner une valeur, donc si votre code a des instructions de branchement (comme une construction if/else), tous les chemins possibles doivent avoir un retour. Par exemple, si vous avez un return à l'intérieur d'un bloc if mais pas après, l'éditeur affichera une erreur car si le bloc n'est pas exécuté, la fonction n'aura pas de valeur valide à retourner.
Référencer des fonctions
Les fonctions sont des valeurs de première classe en termes d'objet Callable. Le référencement d'une fonction par son nom sans l'appeler génère automatiquement l'objet Callable approprié. Cela peut être utilisé pour passer des fonctions en tant qu'arguments.
func map(arr: Array, function: Callable) -> Array:
var result = []
for item in arr:
result.push_back(function.call(item))
return result
func add1(value: int) -> int:
return value + 1;
func _ready() -> void:
var my_array = [1, 2, 3]
var plus_one = map(my_array, add1)
print(plus_one) # Prints `[2, 3, 4]`.
Note
Les callables doivent être appelés avec la méthode call(). Vous ne pouvez pas utiliser directement l'opérateur (). Ce comportement est implémenté pour éviter les problèmes de performances lors des appels directs de fonction.
Fonctions Lambda
Les fonctions Lambda vous permettent de déclarer des fonctions qui n'appartiennent pas à une classe. À la place, un objet Callable est créé et assigné directement à une variable. Cela peut être utile pour créer des objets Callable à transmettre sans polluer la portée de la classe.
var lambda = func (x):
print(x)
To call the created lambda you can use the call() method:
lambda.call(42) # Prints `42`.
Lambda functions can be named for debugging purposes (the name is displayed in the Debugger):
var lambda = func my_lambda(x):
print(x)
You can specify type hints for lambda functions in the same way as for regular ones:
var lambda := func (x: int) -> void:
print(x)
Note that if you want to return a value from a lambda function, an explicit return
is required (you can't omit return):
var lambda = func (x): return x ** 2
print(lambda.call(2)) # Prints `4`.
Lambda functions capture the local environment:
var x = 42
var lambda = func ():
print(x) # Prints `42`.
lambda.call()
Avertissement
Local variables are captured by value once, when the lambda is created. So they won't be updated in the lambda if reassigned in the outer function:
var x = 42
var lambda = func (): print(x)
lambda.call() # Prints `42`.
x = "Hello"
lambda.call() # Prints `42`.
Also, a lambda cannot reassign an outer local variable. After exiting the lambda, the variable will be unchanged, because the lambda capture implicitly shadows it:
var x = 42
var lambda = func ():
print(x) # Prints `42`.
x = "Hello" # Produces the `CONFUSABLE_CAPTURE_REASSIGNMENT` warning.
print(x) # Prints `Hello`.
lambda.call()
print(x) # Prints `42`.
However, if you use pass-by-reference data types (arrays, dictionaries, and objects), then the content changes are shared until you reassign the variable:
var a = []
var lambda = func ():
a.append(1)
print(a) # Prints `[1]`.
a = [2] # Produces the `CONFUSABLE_CAPTURE_REASSIGNMENT` warning.
print(a) # Prints `[2]`.
lambda.call()
print(a) # Prints `[1]`.
Fonctions statiques
A function can be declared static. When a function is static, it has no access to the instance member variables or self.
A static function has access to static variables. Also static functions are useful to make libraries of helper functions:
static func sum2(a, b):
return a + b
Les fonctions Lambda ne peuvent pas être déclarées statiques.
Voir aussi Static variables et Static constructor.
Variadic functions
A variadic function is a function that can take a variable number of arguments. Since Godot 4.5, GDScript supports variadic functions. To declare a variadic function, you need to use the rest parameter, which collects all the excess arguments into an array.
func my_func(a, b = 0, ...args):
prints(a, b, args)
func _ready():
my_func(1) # 1 0 []
my_func(1, 2) # 1 2 []
my_func(1, 2, 3) # 1 2 [3]
my_func(1, 2, 3, 4) # 1 2 [3, 4]
my_func(1, 2, 3, 4, 5) # 1 2 [3, 4, 5]
A function can have at most one rest parameter, which must be the last one in the parameter list. The rest parameter cannot have a default value. Static and lambda functions can also be variadic.
Static typing works for variadic functions too. However, typed arrays are currently not supported as a static type of the rest parameter:
# You cannot specify `...values: Array[int]`.
func sum(...values: Array) -> int:
var result := 0
for value in values:
assert(value is int)
result += value
return result
Note
Although you can declare functions as variadic using the rest parameter, unpacking parameters
when calling a function using spread syntax that exists in some languages (JavaScript, PHP)
is currently not supported in GDScript. However, you can use callv() to call a function
with an array of arguments:
func test_func(...args):
#log_data(...args) # This won't work.
log_data.callv(args) # This will work.
func log_data(...values):
# You should use `callv()` if you want to pass `values` as the argument list,
# rather than passing the array as the first argument.
prints.callv(values)
# You can use array concatenation to prepend/append the argument list.
write_data.callv(["user://log.txt"] + values)
func write_data(path, ...values):
# ...
Abstract functions
Instructions et flux de contrôle
Les instructions sont standard et peuvent être des affectations, des appels de fonctions, des structure de contrôle, etc (voir ci-dessous). ; utilisé comme séparateur d'instructions est entièrement facultatif.
Expressions
Les expressions sont des séquences d'opérateurs et de leurs opérandes de manière ordonnée. Une expression en elle-même peut également être une déclaration, bien que seuls les appels soient raisonnables pour être utilisés comme déclarations, car les autres expressions n'ont pas d'effets secondaires.
Les expressions renvoient des valeurs qui peuvent être affectées à des cibles valides. Les opérandes d'un opérateur peuvent être une autre expression. Une affectation n'est pas une expression et ne renvoie donc aucune valeur.
Here are some examples of expressions:
2 + 2 # Binary operation.
-5 # Unary operation.
"okay" if x > 4 else "not okay" # Ternary operation.
x # Identifier representing variable or constant.
x.a # Attribute access.
x[4] # Subscript access.
x > 2 or x < 5 # Comparisons and logic operators.
x == y + 2 # Equality test.
do_something() # Function call.
[1, 2, 3] # Array definition.
{A = 1, B = 2} # Dictionary definition.
preload("res://icon.svg") # Preload builtin function.
self # Reference to current instance.
Les identifiants, les attributs et les indices sont des cibles d'affectation valides. Les autres expressions ne peuvent pas se trouver à gauche d'une affectation.
self
self can be used to refer to the current instance and is often equivalent to
directly referring to symbols available in the current script. However, self
also allows you to access properties, methods, and other names that are defined
dynamically (i.e. are expected to exist in subtypes of the current class, or are
provided using _set() and/or
_get()).
extends Node
func _ready():
# Compile time error, as `my_var` is not defined in the current class or its ancestors.
print(my_var)
# Checked at runtime, thus may work for dynamic properties or descendant classes.
print(self.my_var)
# Compile time error, as `my_func()` is not defined in the current class or its ancestors.
my_func()
# Checked at runtime, thus may work for descendant classes.
self.my_func()
Avertissement
Beware that accessing members of child classes in the base class is often considered a bad practice, because this blurs the area of responsibility of any given piece of code, making the overall relationship between parts of your game harder to reason about. Besides that, one can simply forget that the parent class had some expectations about it's descendants.
if/else/elif (si / sinon / sinon-si)
Les conditions simples sont créées en utilisant la syntaxe if/else/elif. Les parenthèses autour des conditions sont autorisées, mais pas obligatoires. Étant donné la nature de l'indentation par tabulations, elif peut être utilisé à la place de else/if pour maintenir un niveau d'indentation raisonnable.
if (expression):
statement(s)
elif (expression):
statement(s)
else:
statement(s)
Short statements can be written on the same line as the condition:
if 1 + 1 == 2: return 2 + 2
else:
var x = 3 + 3
return x
Sometimes, you might want to assign a different initial value based on a boolean expression. In this case, ternary-if expressions come in handy:
var x = (value) if (expression) else (value)
y += 3 if y < 10 else -1
Ternary-if expressions can be nested to handle more than 2 cases. When nesting ternary-if expressions, it is recommended to wrap the complete expression over multiple lines to preserve readability:
var count = 0
var fruit = (
"apple" if count == 2
else "pear" if count == 1
else "banana" if count == 0
else "orange"
)
print(fruit) # banana
# Alternative syntax with backslashes instead of parentheses (for multi-line expressions).
# Less lines required, but harder to refactor.
var fruit_alt = \
"apple" if count == 2 \
else "pear" if count == 1 \
else "banana" if count == 0 \
else "orange"
print(fruit_alt) # banana
You may also wish to check if a value is contained within something. You can
use an if statement combined with the in operator to accomplish this:
# Check if a letter is in a string.
var text = "abc"
if 'b' in text: print("The string contains b")
# Check if a variable is contained within a node.
if "varName" in get_parent(): print("varName is defined in parent!")
while
Les boucles simples sont créées en utilisant la syntaxe while. Les boucles peuvent être interrompues à l'aide de break ou continuées à l'aide de continue (qui passe à l'itération suivante de la boucle sans exécuter de code supplémentaire dans l'itération en cours) :
while (expression):
statement(s)
for
Pour itérer à travers une plage, telle qu'un tableau ou une table, une boucle for est utilisée. Lors de l'itération dans un tableau, l'élément courant du tableau est stocké dans la variable de la boucle. Lors de l'itération sur un dictionnaire, la key est stockée dans la variable de la boucle.
for x in [5, 7, 11]:
statement # Loop iterates 3 times with 'x' as 5, then 7 and finally 11.
var names = ["John", "Marta", "Samantha", "Jimmy"]
for name: String in names: # Typed loop variable.
print(name) # Prints name's content.
var dict = {"a": 0, "b": 1, "c": 2}
for i in dict:
print(dict[i]) # Prints 0, then 1, then 2.
for i in range(3):
statement # Similar to [0, 1, 2] but does not allocate an array.
for i in range(1, 3):
statement # Similar to [1, 2] but does not allocate an array.
for i in range(2, 8, 2):
statement # Similar to [2, 4, 6] but does not allocate an array.
for i in range(8, 2, -2):
statement # Similar to [8, 6, 4] but does not allocate an array.
for c in "Hello":
print(c) # Iterate through all characters in a String, print every letter on new line.
for i in 3:
statement # Similar to range(3).
for i in 2.2:
statement # Similar to range(ceil(2.2)).
Si vous souhaitez attribuer des valeurs à un tableau pendant son itération, il est préférable d'utiliser for i in array.size().
for i in array.size():
array[i] = "Hello World"
La variable de la boucle est locale à la boucle for et changer sa valeur ne modifiera pas la valeur du tableau. Les objets passés par référence (tels que les nœuds) peuvent toujours être manipulés en appelant des méthodes sur la variable de la boucle.
for string in string_array:
string = "Hello World" # This has no effect
for node in node_array:
node.add_to_group("Cool_Group") # This has an effect
match
L'instruction match est utilisée pour réaliser un branchement de l’exécution d'un programme. Elle est semblable à l'instruction switch présente en beaucoup d'autres langages mais elle procure cependant quelques fonctionnalités supplémentaires.
Avertissement
match est plus strict en termes de type que l'opérateur ==. Par exemple, 1 ne correspondra pas à 1.0. La seule exception est la correspondance String vs StringName : par exemple, la chaîne "hello" est considérée comme égale à la chaîne &"hello".
Syntaxe de base
match <test value>:
<pattern(s)>:
<block>
<pattern(s)> when <pattern guard>:
<block>
<...>
Cours intensif pour les personnes familiarisées avec les instructions switch
Remplacez
switchparmatch.Supprimer
case.Supprimez tous les
break.Remplacer
defaultpar un unique underscore (_).
Contrôle du flux d’exécution
Les motifs sont comparés de haut en bas. Si un motif correspond, le premier bloc correspondant sera exécuté. Ensuite, l'exécution se poursuit en dessous de l'instruction match.
Note
Le mot clé continue dans match pris en charge dans 3.x a été supprimé dans Godot 4.0.
Les types de motifs suivants sont disponibles :
- Motif littéral
Matches a literal:
match x: 1: print("We are number one!") 2: print("Two are better than one!") "test": print("Oh snap! It's a string!")
- Motif d'expression
Matches a constant expression, an identifier, or an attribute access (
A.B):match typeof(x): TYPE_FLOAT: print("float") TYPE_STRING: print("text") TYPE_ARRAY: print("array")
- Motif générique (joker/wildcard)
Ce motif correspond à toutes les possibilités. il est écrit sous la forme d'un simple underscore (_).
It can be used as the equivalent of the
defaultin aswitchstatement in other languages:match x: 1: print("It's one!") 2: print("It's one times two!") _: print("It's not 1 or 2. I don't care to be honest.")
- Motif de liaison
A binding pattern introduces a new variable. Like the wildcard pattern, it matches everything - and also gives that value a name. It's especially useful in array and dictionary patterns:
match x: 1: print("It's one!") 2: print("It's one times two!") var new_var: print("It's not 1 or 2, it's ", new_var)
- Motif de tableau
Il correspond à un tableau. Chaque élément du motif de tableau est un motif lui-même, de sorte que vous pouvez les imbriquer.
La longueur du tableau est d'abord testée, elle doit être de la même taille que l'expression, sinon cette dernière ne correspondra pas.
Tableau ouvert : Un tableau peut être plus grand que l'expression en faisant de
..la dernière sous-expression.Chaque sous-expression doit être séparée par des virgules.
match x: []: print("Empty array") [1, 3, "test", null]: print("Very specific array") [var start, _, "test"]: print("First element is ", start, ", and the last is \"test\"") [42, ..]: print("Open ended array")
- Motif de dictionnaire
Fonctionne de la même manière que le motif du tableau. Chaque clé doit être une expression constante.
La taille du dictionnaire est d'abord testée, elle doit être de la même taille que l'expression, sinon l'expression ne correspondra pas.
Dictionnaire ouvert : Un dictionnaire peut être plus grand que l'expression en faisant de
..le dernier sous-modèle.Chaque sous-expression doit être séparée par des virgules.
Si vous ne spécifiez pas de valeur, seule l'existence de la clé est vérifiée.
Le motif de valeur est séparée du motif de clé par un
:.match x: {}: print("Empty dict") {"name": "Dennis"}: print("The name is Dennis") {"name": "Dennis", "age": var age}: print("Dennis is ", age, " years old.") {"name", "age"}: print("Has a name and an age, but it's not Dennis :(") {"key": "godotisawesome", ..}: print("I only checked for one entry and ignored the rest")
- Motifs multiples
Vous pouvez également spécifier plusieurs motifs séparées par une virgule. Ces motifs ne peuvent être des motifs de liaisons.
match x: 1, 2, 3: print("It's 1 - 3") "Sword", "Splash potion", "Fist": print("Yep, you've taken damage")
Expression de garde
A pattern guard is an optional condition that follows the pattern list
and allows you to make additional checks before choosing a match branch.
Unlike a pattern, a pattern guard can be an arbitrary expression.
Only one branch can be executed per match. Once a branch is chosen, the rest are not checked.
If you want to use the same pattern for multiple branches or to prevent choosing a branch with too general pattern,
you can specify a pattern guard after the list of patterns with the when keyword:
match point:
[0, 0]:
print("Origin")
[_, 0]:
print("Point on X-axis")
[0, _]:
print("Point on Y-axis")
[var x, var y] when y == x:
print("Point on line y = x")
[var x, var y] when y == -x:
print("Point on line y = -x")
[var x, var y]:
print("Point (%s, %s)" % [x, y])
If there is no matching pattern for the current branch, the pattern guard is not evaluated and the patterns of the next branch are checked.
If a matching pattern is found, the pattern guard is evaluated.
Si c'est vrai, alors le corps de la branche est exécuté et
matchse termine.Si c'est faux, alors les motifs de la branche suivante sont vérifiés.
Classes
By default, all script files are unnamed classes. In this case, you can only
reference them using the file's path, using either a relative or an absolute
path. For example, if you name a script file character.gd:
# Inherit from 'character.gd'.
extends "res://path/to/character.gd"
# Load character.gd and create a new node instance from it.
var Character = load("res://path/to/character.gd")
var character_node = Character.new()
Enregistrement de classes nommées
You can give your class a name to register it as a new type in Godot's
editor. For that, you use the class_name keyword. You can optionally use
the @icon annotation with a path to an image, to use it as an icon. Your
class will then appear with its new icon in the editor:
# item.gd
@icon("res://interface/icons/item.png")
class_name Item
extends Node
Astuce
Les images SVG utilisées comme icônes personnalisées de nœuds doivent avoir les options d'import Éditeur > Mettre à l'échelle avec l'échelle de l'éditeur et Éditeur > Convertir les icônes avec le thème de l'éditeur activées. Cela permet aux icônes de suivre l'échelle de l'éditeur et les paramètres de thème si les icônes sont conçues avec la même palette de couleurs que les icônes de Godot.
Voici un exemple de fichier de classe :
# Saved as a file named 'character.gd'.
class_name Character
var health = 5
func print_health():
print(health)
func print_this_script_three_times():
print(get_script())
print(ResourceLoader.load("res://character.gd"))
print(Character)
If you want to use extends too, you can keep both on the same line:
class_name MyNode extends Node
Named classes are globally registered, which means they become available to use
in other scripts without the need to load or preload them:
var player
func _ready():
player = Character.new()
Note
Godot initialise les variables non statiques à chaque fois que vous créez une instance, y compris les tableaux et les dictionnaires. Cela est dans l'esprit de la sécurité des threads, car les scripts peuvent être initialisés dans des threads séparés sans que l'utilisateur ne le sache.
Avertissement
The Godot editor will hide these custom classes with names that begin with the prefix "Editor" in the 'Create New Node' or 'Create New Scene' dialog windows. The classes are available for instantiation at runtime via their class names, but are automatically hidden by the editor windows along with the built-in editor nodes used by the Godot editor.
Abstract classes and methods
Since Godot 4.5, you can define abstract classes and methods using
the @abstract annotation.
An abstract class is a class that cannot be instantiated directly. Instead, it is meant to be inherited by other classes. Attempting to instantiate an abstract class will result in an error.
An abstract method is a method that has no implementation. Therefore, a newline or a semicolon is expected after the function header. This defines a contract that inheriting classes must conform to, because the method signature must be compatible when overriding.
Inheriting classes must either provide implementations for all abstract methods, or the inheriting class must be marked as abstract. If a class has at least one abstract method (either its own or an unimplemented inherited one), then it must also be marked as abstract. However, the reverse is not true: an abstract class is allowed to have no abstract methods.
Astuce
If you want to declare a method as optional to be overridden, you should use a non-abstract method and provide a default implementation.
For example, you could have an abstract class called Shape that defines
an abstract method called draw(). You can then create subclasses like Circle
and Square that implement the draw() method in their own way.
This allows you to define a common interface for all shapes without
having to implement all the details in the abstract class itself:
@abstract class Shape:
@abstract func draw()
# This is a concrete (non-abstract) subclass of Shape.
# You **must** implement all abstract methods in concrete classes.
class Circle extends Shape:
func draw():
print("Drawing a circle.")
class Square extends Shape:
func draw():
print("Drawing a square.")
Both inner classes and classes created using class_name can be abstract.
This example creates two abstract classes, one of which is a subclass of another
abstract class:
@abstract
class_name AbstractClass
extends Node
@abstract class AbstractInnerClass:
func _ready():
pass
# This is an example of a concrete subclass of `AbstractInnerClass`.
# This class can be instantiated using `AbstractClass.ConcreteInnerClass.new()`
# in other scripts, even though it's part of an abstract `class_name` script.
class ConcreteInnerClass extends AbstractInnerClass:
func _ready():
print("Concrete class ready.")
Avertissement
Since an abstract class cannot be instantiated, it is not possible to attach an abstract class to a node. If you attempt to do so, the engine will print an error when running the scene:
Cannot set object script. Script '<path to script>' should not be abstract.
Unnamed classes can also be defined as abstract, the @abstract annotation
must precede extends:
@abstract
extends Node
Héritage
Une classe (stockée sous forme de fichier) peut hériter de :
Une classe globale.
Un autre fichier de classe.
Une classe interne à l'intérieur d'un autre fichier de classe.
L'héritage multiple n'est pas autorisé.
Inheritance uses the extends keyword:
# Inherit/extend a globally available class.
extends SomeClass
# Inherit/extend a named class file.
extends "somefile.gd"
# Inherit/extend an inner class in another file.
extends "somefile.gd".SomeInnerClass
Note
Si l'héritage n'est pas explicitement défini, la classe héritera par défaut de RefCounted.
To check if a given instance inherits from a given class,
the is keyword can be used:
# Cache the enemy class.
const Enemy = preload("enemy.gd")
# [...]
# Use 'is' to check inheritance.
if entity is Enemy:
entity.apply_damage()
To call a function in a super class (i.e. one extend-ed in your current
class), use the super keyword:
super(args)
This is especially useful because functions in extending classes replace
functions with the same name in their super classes. If you still want to
call them, you can use super:
func some_func(x):
super(x) # Calls the same function on the super class.
If you need to call a different function from the super class, you can specify the function name with the attribute operator:
func overriding():
return 0 # This overrides the method in the base class.
func dont_override():
return super.overriding() # This calls the method as defined in the base class.
Avertissement
L'une des mauvaises pratiques les plus courantes consiste à essayer de remplacer les méthodes non virtuelles de moteur telles que get_class(), queue_free(), etc. Ceci n'est pas pris en charge pour des raisons techniques.
Dans Godot 3, vous pouvez masquer les méthodes du moteur dans GDScript, et cela fonctionnera si vous appelez cette méthode dans GDScript. Cependant, le moteur n'exécutera pas votre code si la méthode est appelée à l'intérieur du moteur lors d'un événement.
Dans Godot 4, le masquage ne fonctionne pas toujours, car GDScript optimise les appels de méthodes natives. Par conséquent, nous avons ajouté l'avertissement NATIVE_METHOD_OVERRIDE, qui est traité comme une erreur par défaut. Nous vous déconseillons fortement de désactiver ou d'ignorer l'avertissement.
Notez que cela ne s'applique pas aux méthodes virtuelles telles que _ready(), _process() et autres (marquées avec le qualificateur virtual dans la documentation et dont les noms commencent par un trait de soulignement). Ces méthodes sont spécifiquement destinées à personnaliser le comportement du moteur et peuvent être remplacées dans GDScript. Les signaux et les notifications peuvent également être utiles à ces fins.
Constructeur de classe
The class constructor, called on class instantiation, is named _init. If you
want to call the base class constructor, you can also use the super syntax.
Note that every class has an implicit constructor that is always called
(defining the default values of class variables). super is used to call the
explicit constructor:
func _init(arg):
super("some_default", arg) # Call the custom base constructor.
This is better explained through examples. Consider this scenario:
# state.gd (inherited class).
var entity = null
var message = null
func _init(e = null):
entity = e
func enter(m):
message = m
# idle.gd (inheriting class).
extends "state.gd"
func _init(e = null, m = null):
super(e)
# Do something with 'e'.
message = m
Il y a plusieurs choses à garder à l'esprit ici :
If the inherited class (
state.gd) defines an_initconstructor that takes arguments (ein this case), then the inheriting class (idle.gd) must define_initas well and pass appropriate parameters to_initfromstate.gd.idle.gdpeut avoir un nombre différent d'arguments que la classe parentstate.gd.Dans l'exemple ci-dessus, le
equi est passé au constructeurstate.gd, est le mêmeepassé àidle.gd.If
idle.gd's_initconstructor takes 0 arguments, it still needs to pass some value to thestate.gdbase class, even if it does nothing. This brings us to the fact that you can pass expressions to the base constructor as well, not just variables, e.g.:
# idle.gd
func _init():
super(5)
Constructeur statique
A static constructor is a static function _static_init that is called automatically
when the class is loaded, after the static variables have been initialized:
static var my_static_var = 1
static func _static_init():
my_static_var = 2
Un constructeur statique ne peut pas prendre d’arguments et ne doit renvoyer aucune valeur.
Classes internes
Un fichier de classe peut contenir des classes internes. Les classes internes sont définies à l'aide du mot-clé class. Ils sont instanciés à l'aide de la fonction ClassName.new().
# Inside a class file.
# An inner class in this class file.
class SomeInnerClass:
var a = 5
func print_value_of_a():
print(a)
# This is the constructor of the class file's main class.
func _init():
var c = SomeInnerClass.new()
c.print_value_of_a()
Les classes comme ressources
Classes stored as files are treated as GDScripts. They
must be loaded from disk to access them in other classes. This is done using
either the load or preload functions (see below). Instancing of a loaded
class resource is done by calling the new function on the class object:
# Load the class resource when calling load().
var MyClass = load("myclass.gd")
# Preload the class only once at compile time.
const MyClass = preload("myclass.gd")
func _init():
var a = MyClass.new()
a.some_function()
Exports
Note
La documentation à propos des exports a été déplacé vers GDScript Propriétés exportées.
Propriétés (setters et getters)
Parfois, vous souhaitez qu'une variable membre d'une classe fasse plus que simplement contenir des données et effectue une validation ou un calcul à chaque fois que sa valeur change. Il peut également être souhaitable d'encapsuler son accès d'une manière ou d'une autre.
Pour cela, GDScript fournit une syntaxe spéciale pour définir des propriétés à l'aide des mots-clés set et get après une déclaration de variable. Vous pouvez ensuite définir un bloc de code qui sera exécuté lorsque la variable sera consultée ou affectée.
Exemple :
var milliseconds: int = 0
var seconds: int:
get:
return milliseconds / 1000
set(value):
milliseconds = value * 1000
Note
Contrairement à setget dans les versions précédentes de Godot, les méthodes set et get sont toujours appelées (sauf quand indiqué ci-dessous), même lorsqu'elles sont utilisées à l'intérieur de la même classe (avec ou sans le préfixe self .). Cela rend le comportement cohérent. Si vous avez besoin d'un accès direct à la valeur, utilisez une autre variable pour l'accès direct et faites en sorte que le code de la propriété utilise ce nom.
Syntaxe alternative
Also there is another notation to use existing class functions if you want to split the code from the variable declaration or you need to reuse the code across multiple properties (but you can't distinguish which property the setter/getter is being called for):
var my_prop:
get = get_my_prop, set = set_my_prop
This can also be done in the same line:
var my_prop: get = get_my_prop, set = set_my_prop
Le setter et le getter doivent utiliser la même notation, le mélange de styles pour la même variable n'est pas autorisé.
Note
Vous ne pouvez pas spécifier d'indications de type pour les fonctions setter et getter en ligne. Cela est fait exprès pour réduire le code sans intérêt. Si la variable est typée, alors l'argument du setter est automatiquement du même type et la valeur de retour du getter doit lui correspondre. Les fonctions setter/getter séparées peuvent avoir des indications de type et le type doit correspondre au type de la variable ou être un type plus large.
Quand les setter/getter ne sont pas appelés
Lorsqu'une variable est initialisée, la valeur initiale sera écrite directement dans la variable. Y compris si l'annotation @onready est appliquée à la variable.
Using the variable's name to set it inside its own setter or to get it inside its own getter will directly access the underlying member, so it won't generate infinite recursion and saves you from explicitly declaring another variable:
signal changed(new_value)
var warns_when_changed = "some value":
get:
return warns_when_changed
set(value):
changed.emit(value)
warns_when_changed = value
This also applies to the alternative syntax:
var my_prop: set = set_my_prop
func set_my_prop(value):
my_prop = value # No infinite recursion.
Avertissement
The exception does not propagate to other functions called in the setter/getter. For example, the following code will cause an infinite recursion:
var my_prop:
set(value):
set_my_prop(value)
func set_my_prop(value):
my_prop = value # Infinite recursion, since `set_my_prop()` is not the setter.
Mode tool(outil)
By default, scripts don't run inside the editor and only the exported
properties can be changed. In some cases, it is desired that they do run
inside the editor (as long as they don't execute game code or manually
avoid doing so). For this, the @tool annotation exists and must be
placed at the top of the file:
@tool
extends Button
func _ready():
print("Hello")
Voir Exécuter le code dans l'éditeur pour plus d'informations.
Avertissement
Faites attention en supprimant des nœuds avec queue_free() ou free() dans un script outil (en particulier le propriétaire du script). Puisque les scripts outils s'exécutent dans l'éditeur, une erreur pourrait le faire crasher.
Gestion de la mémoire
Godot implémente le comptage de références pour libérer certaines instances qui ne sont plus utilisées, au lieu d'un ramasse-miettes (garbage collector), ou nécessitant une gestion purement manuelle. Toute instance de la classe RefCounted (ou toute classe qui en hérite, comme Resource) sera libérée automatiquement lorsqu'elle n'est plus utilisée. Pour une instance de toute classe qui n'est pas une RefCounted (comme Node ou le type de base Object), elle restera en mémoire jusqu'à ce qu'elle soit supprimée avec free() (ou queue_free() pour les Nodes).
Note
Si un Node est supprimé via free() ou queue_free(), tous ses enfants seront également supprimés de manière récursive.
Pour éviter les références cycliques qui ne peuvent pas être libérés, une fonction WeakRef est fournie pour créer des références faibles, qui permettent d'accéder à l'objet sans empêcher un RefCounted de se libérer. Voici un exemple :
extends Node
var my_file_ref
func _ready():
var f = FileAccess.open("user://example_file.json", FileAccess.READ)
my_file_ref = weakref(f)
# the FileAccess class inherits RefCounted, so it will be freed when not in use
# the WeakRef will not prevent f from being freed when other_node is finished
other_node.use_file(f)
func _this_is_called_later():
var my_file = my_file_ref.get_ref()
if my_file:
my_file.close()
Alternativement, quand vous n'utilisez pas de références, le is_instance_valid(instance) peut être utilisé pour vérifier si un objet a été libéré.
Signaux
Les signaux sont un outil permettant d’émettre des messages à partir d’un objet auquel d’autres objets peuvent réagir. Pour créer des signaux personnalisés pour une classe, utilisez le mot-clé signal.
extends Node
# A signal named health_depleted.
signal health_depleted
Note
Les signaux sont comme des fonctions de rappel. Ils remplissent également le rôle d'Observateurs, un modèle de conception courant en programmation. Pour plus d'informations, lisez le tutoriel sur les Observateurs (en anglais), de l'e-book Game Programming Patterns.
Vous pouvez connecter ces signaux à des méthodes de la même manière que vous connectez les signaux intégrés de nœuds tels que Button ou RigidBody3D.
In the example below, we connect the health_depleted signal from a
Character node to a Game node. When the Character node emits the
signal, the game node's _on_character_health_depleted is called:
# game.gd
func _ready():
var character_node = get_node('Character')
character_node.health_depleted.connect(_on_character_health_depleted)
func _on_character_health_depleted():
get_tree().reload_current_scene()
Vous pouvez émettre autant d'arguments que vous souhaitez avec un signal.
Voici un exemple où cela est utile. Si nous voulons ajouter une barre de vie qui s'anime quand les points de vie changent, mais nous souhaitons séparer l'interface utilisateur du joueur dans notre arbre de scène.
In our character.gd script, we define a health_changed signal and emit
it with Signal.emit(), and from
a Game node higher up our scene tree, we connect it to the Lifebar using
the Signal.connect() method:
# character.gd
...
signal health_changed
func take_damage(amount):
var old_health = health
health -= amount
# We emit the health_changed signal every time the
# character takes damage.
health_changed.emit(old_health, health)
...
# lifebar.gd
# Here, we define a function to use as a callback when the
# character's health_changed signal is emitted.
...
func _on_Character_health_changed(old_value, new_value):
if old_value > new_value:
progress_bar.modulate = Color.RED
else:
progress_bar.modulate = Color.GREEN
# Imagine that `animate` is a user-defined function that animates the
# bar filling up or emptying itself.
progress_bar.animate(old_value, new_value)
...
Dans le nœud Game, on récupère les nœuds Character et Lifebar puis on connecte le personnage, qui émet le signal, au récepteur c'est-à-dire Lifebar dans notre cas.
# game.gd
func _ready():
var character_node = get_node('Character')
var lifebar_node = get_node('UserInterface/Lifebar')
character_node.health_changed.connect(lifebar_node._on_Character_health_changed)
Cela permet alors à la Lifebar de réagir aux changements de points de vie sans avoir à la coupler au nœud Character.
You can write optional argument names in parentheses after the signal's definition:
# Defining a signal that forwards two arguments.
signal health_changed(old_value, new_value)
These arguments show up in the editor's Signals dock, and Godot can use them to generate callback functions for you. However, you can still emit any number of arguments when you emit signals; it's up to you to emit the correct values.
You can also create copies of GDScript Callable objects which accept additional arguments using Callable.bind(). This allows you to add extra information to the connection if the emitted signal itself doesn't give you access to all the data that you need.
When the signal is emitted, the callback method receives the bound values, in addition to those provided by the signal.
Building on the example above, let's say we want to display a log of the damage
taken by each character on the screen, like Player1 took 22 damage.. The
health_changed signal doesn't give us the name of the character that took
damage. So when we connect the signal to the in-game console, we can add the
character's name using the bind method:
# game.gd
func _ready():
var character_node = get_node('Character')
var battle_log_node = get_node('UserInterface/BattleLog')
character_node.health_changed.connect(battle_log_node._on_Character_health_changed.bind(character_node.name))
Our BattleLog node receives each bound element as an extra argument:
# battle_log.gd
func _on_Character_health_changed(old_value, new_value, character_name):
if not new_value <= old_value:
return
var damage = old_value - new_value
label.text += character_name + " took " + str(damage) + " damage."
En attente de signaux ou de coroutines
Le mot-clé await peut être utilisé pour créer des coroutines qui attendent qu'un signal soit émis avant de continuer l'exécution. L'utilisation du mot-clé await avec un signal ou un appel de fonction qui est également une coroutine rendra immédiatement le contrôle à l'appelant. Lorsque le signal est émis (ou que la coroutine appelée se termine), elle reprendra l'exécution à partir du point où elle s'est arrêtée.
For example, to stop execution until the user presses a button, you can do something like this:
func wait_confirmation():
print("Prompting user")
await $Button.button_up # Waits for the button_up signal from Button node.
print("User confirmed")
return true
In this case, the wait_confirmation becomes a coroutine, which means that the caller also needs to await it:
func request_confirmation():
print("Will ask the user")
var confirmed = await wait_confirmation()
if confirmed:
print("User confirmed")
else:
print("User cancelled")
Note that requesting a coroutine's return value without await will trigger an error:
func wrong():
var confirmed = wait_confirmation() # Will give an error.
However, if you don't depend on the result, you can just call it asynchronously, which won't stop execution and won't make the current function a coroutine:
func okay():
wait_confirmation()
print("This will be printed immediately, before the user press the button.")
If you use await with an expression that isn't a signal nor a coroutine, the value will be returned immediately and the function won't give the control back to the caller:
func no_wait():
var x = await get_five()
print("This doesn't make this function a coroutine.")
func get_five():
return 5
This also means that returning a signal from a function that isn't a coroutine will make the caller await that signal:
func get_signal():
return $Button.button_up
func wait_button():
await get_signal()
print("Button was pressed")
Note
Contrairement à yield dans les versions précédentes de Godot, vous ne pouvez pas obtenir l'objet correspondant à l'état de la fonction. Cela est fait pour garantir la sécurité des types. Avec cette sécurité en place, une fonction ne peut pas dire qu'elle renvoie un int alors qu'elle renvoie en fait un objet d'état correspondant à l'état de la fonction pendant l'exécution.
You can store the arguments passed to the signal's parameters. If there is only one parameter, the awaited value will have the same type as the argument:
func toggled():
var signal_args = await $Button.toggled
assert(typeof(signal_args) == TYPE_BOOL)
If there is more than one parameter, the awaited value will be of type Array:
func request_completed():
var signal_args = await $HTTPRequest.request_completed
assert(typeof(signal_args) == TYPE_ARRAY)
Otherwise, the awaited value will be null:
func button_up():
var signal_args = await $Button.button_up
assert(signal_args == null)
Mot-clé d'assertion
Le mot-clé assert sert à vérifier une condition dans une compilation de débogage. Ces assertions sont ignorées dans les compilations sans débogage. Cela signifie que l'expression passée en argument ne sera pas évaluée dans un projet exporté en mode release. De ce fait, les assertions ne doivent pas contenir des expressions ayant des effets secondaires. Sinon, le comportement du script variera selon s'il est exécuté dans une compilation de débogage ou de release.
# Check that 'i' is 0. If 'i' is not 0, an assertion error will occur.
assert(i == 0)
Lors de l'exécution d'un projet depuis l'éditeur, celui-ci sera mis en pause en cas d'erreur d'assertion.
You can optionally pass a custom error message to be shown if the assertion fails:
assert(enemy_power < 256, "Enemy is too powerful!")
Commentaires
Tout ce qui se trouve entre un
#et la fin de la ligne est ignoré et considéré comme un commentaire.# This is a comment.Astuce
Dans l'éditeur de script Godot, des mots-clés spéciaux sont mis en évidence dans les commentaires pour attirer l'attention de l'utilisateur sur des commentaires spécifiques :
Critique (apparaît en rouge) :
ALERT,ATTENTION,CAUTION,CRITICAL,DANGER,SECURITYAvertissement (apparaît en jaune) :
BUG,DEPRECATED,FIXME,HACK,TASK,TBD,TODO,WARNINGInformation (apparaît en vert) :
INFO,NOTE,NOTICE,TEST,TESTINGCes mots-clés sont sensibles à la casse, ils doivent donc être écrits en majuscules pour être reconnus :
La liste des mots-clés mis en surbrillance et leurs couleurs peuvent être modifiés dans la section Éditeur de texte > Thème > Marqueurs de commentaires des paramètres de l'éditeur.
Use two hash symbols (
##) instead of one (#) to add a documentation comment, which will appear in the script documentation and in the inspector description of an exported variable. Documentation comments must be placed directly above a documentable item (such as a member variable), or at the top of a file. Dedicated formatting options are also available. See GDSCript Commentaires de documentation for details.