Up to date
This page is up to date for Godot 4.3.
If you still find outdated information, please open an issue.
Guide de style GDScript
Ce guide de style liste les standards pour écrire du GDScript élégant. Le but est d'encourager l'écriture de code propre et lisible ainsi que de promouvoir l'uniformité au travers des projets, les discussions et les tutoriels. Nous espérons que cela encouragera le développement d'outil d'auto-formatage.
Puisque GDScript ressemble à Python, ce guide est inspiré par le guide de style de programmation de Python PEP 8 .
Les guides de style ne sont pas conçus comme des livres de règles rigides. Parfois, il se peut que vous ne puissiez pas appliquer certaines des règles ci-dessous. Lorsque cela se produit, utilisez votre jugement et demandez à vos collègues développeurs de vous donner leur avis.
En général, garder votre code consistant dans vos projets et au sein de votre équipe est plus important que de suivre ce guide à la lettre.
Note
L'éditeur de script intégré dans Godot utilise beaucoup de ces standards par défaut. Laissez-le vous aider.
Voici un exemple de classe complet basé sur ces lignes directrices :
class_name StateMachine
extends Node
## Hierarchical State machine for the player.
##
## Initializes states and delegates engine callbacks ([method Node._physics_process],
## [method Node._unhandled_input]) to the state.
signal state_changed(previous, new)
@export var initial_state: Node
var is_active = true:
set = set_is_active
@onready var _state = initial_state:
set = set_state
@onready var _state_name = _state.name
func _init():
add_to_group("state_machine")
func _enter_tree():
print("this happens before the ready method!")
func _ready():
state_changed.connect(_on_state_changed)
_state.enter()
func _unhandled_input(event):
_state.unhandled_input(event)
func _physics_process(delta):
_state.physics_process(delta)
func transition_to(target_state_path, msg={}):
if not has_node(target_state_path):
return
var target_state = get_node(target_state_path)
assert(target_state.is_composite == false)
_state.exit()
self._state = target_state
_state.enter(msg)
Events.player_state_changed.emit(_state.name)
func set_is_active(value):
is_active = value
set_physics_process(value)
set_process_unhandled_input(value)
set_block_signals(not value)
func set_state(value):
_state = value
_state_name = _state.name
func _on_state_changed(previous, new):
print("state changed")
state_changed.emit()
class State:
var foo = 0
func _init():
print("Hello!")
Formatage
Encodage et caractères spéciaux
Utilisez le saut de ligne (LF) pour terminer les lignes, et non CRLF ou CR. (éditeur par défaut)
Utilisez un caractère de saut de ligne à la fin de chaque fichier. (éditeur par défaut)
Utilisez l'encodage UTF-8 sans indicateur d'ordre d'octet. (éditeur par défaut)
Utilisez Tabs au lieu d'espaces pour l'indentation. (éditeur par défaut)
Indentation
Chaque niveau d'indentation doit être supérieur d'une unité au bloc qui le contient.
Bon :
for i in range(10):
print("hello")
Mauvais :
for i in range(10):
print("hello")
for i in range(10):
print("hello")
Utiliser 2 niveaux d'indentations pour distinguer les suites de lignes des blocs de code réguliers.
Bon :
effect.interpolate_property(sprite, "transform/scale",
sprite.get_scale(), Vector2(2.0, 2.0), 0.3,
Tween.TRANS_QUAD, Tween.EASE_OUT)
Mauvais :
effect.interpolate_property(sprite, "transform/scale",
sprite.get_scale(), Vector2(2.0, 2.0), 0.3,
Tween.TRANS_QUAD, Tween.EASE_OUT)
Les exceptions à cette règle sont les tableaux, les dictionnaires et les énumérations. Utilisez un seul niveau d'indentation pour distinguer les lignes de continuation :
Bon :
var party = [
"Godot",
"Godette",
"Steve",
]
var character_dict = {
"Name": "Bob",
"Age": 27,
"Job": "Mechanic",
}
enum Tiles {
TILE_BRICK,
TILE_FLOOR,
TILE_SPIKE,
TILE_TELEPORT,
}
Mauvais :
var party = [
"Godot",
"Godette",
"Steve",
]
var character_dict = {
"Name": "Bob",
"Age": 27,
"Job": "Mechanic",
}
enum Tiles {
TILE_BRICK,
TILE_FLOOR,
TILE_SPIKE,
TILE_TELEPORT,
}
Virgule de fin
Utilisez une virgule de fin de ligne sur la dernière ligne des tableaux, dictionnaires et énumérations. Ceci a pour résultat un refactoring plus facile et de meilleures différences dans le contrôle de version car la dernière ligne n'a pas besoin d'être modifiée lors de l'ajout de nouveaux éléments.
Bon :
var array = [
1,
2,
3,
]
Mauvais :
var array = [
1,
2,
3
]
Les virgules de fin de ligne sont inutiles dans les listes en une ligne, alors ne les ajoutez pas dans ce cas.
Bon :
var array = [1, 2, 3]
Mauvais :
var array = [1, 2, 3,]
Lignes vides
Encadrer les fonctions et les définitions de classes par deux ligne vide :
func heal(amount):
health += amount
health = min(health, max_health)
health_changed.emit(health)
func take_damage(amount, effect=null):
health -= amount
health = max(0, health)
health_changed.emit(health)
Utiliser une ligne vide à l'intérieur des fonctions pour séparer les sections logiques.
Note
Nous utilisons une seule ligne entre les classes et les définitions de fonctions dans la référence de la classe et dans les courts extraits de code de cette documentation.
Longueur de la ligne
Gardez chaque ligne de code en dessous de 100 caractères.
Si vous le pouvez, essayez de ne pas dépasser 80 caractères par ligne. Cela permet de lire le code sur de petits écrans et avec deux scripts ouverts côte à côte dans un éditeur de texte externe. Par exemple, lorsqu'il s'agit d'une révision différentielle.
Une Instruction par ligne
Évitez de combiner plusieurs instructions sur une seule ligne, y compris les instructions conditionnelles, pour respecter les directives de style GDScript pour plus de lisibilité.
Bon :
if position.x > width:
position.x = 0
if flag:
print("flagged")
Mauvais :
if position.x > width: position.x = 0
if flag: print("flagged")
La seule exception à cette règle est l'opérateur ternaire :
next_state = "idle" if is_on_floor() else "fall"
Formatez les instructions sur plusieurs lignes pour la lisibilité
Quand vous avez des instructions if particulièrement longues ou des expressions ternaires imbriquées, les séparer en plusieurs lignes améliore la lisibilité. Comme les lignes suivantes font parties de la même expression, 2 niveaux d'indentation devraient être utilisés au lieu d'un.
GDScript permet d'écrire des instructions sur plusieurs lignes à l'aide de parenthèses ou d'antislashs. Les parenthèses sont privilégiées dans ce guide de style car elles permettent une refactorisation plus simple. Avec les antislashs, vous devez vous assurer que la dernière ligne ne contient pas un antislash à la fin. Avec les parenthèses, vous n'avez pas à vous soucier d'un antislash à la fin de la dernière ligne.
Quand vous séparez une expression conditionnelle en plusieurs lignes, les mots-clés and/or devraient être placé en début de ligne, et non à la fin de la ligne précédente.
Bon :
var angle_degrees = 135
var quadrant = (
"northeast" if angle_degrees <= 90
else "southeast" if angle_degrees <= 180
else "southwest" if angle_degrees <= 270
else "northwest"
)
var position = Vector2(250, 350)
if (
position.x > 200 and position.x < 400
and position.y > 300 and position.y < 400
):
pass
Mauvais :
var angle_degrees = 135
var quadrant = "northeast" if angle_degrees <= 90 else "southeast" if angle_degrees <= 180 else "southwest" if angle_degrees <= 270 else "northwest"
var position = Vector2(250, 350)
if position.x > 200 and position.x < 400 and position.y > 300 and position.y < 400:
pass
Évitez les parenthèses inutiles
Évitez les parenthèses dans les expressions et les déclarations conditionnelles. À moins qu'elles ne soient nécessaires pour l'ordre des opérations ou qu'elles s'étendent sur plusieurs lignes, elles ne font que réduire la lisibilité.
Bon :
if is_colliding():
queue_free()
Mauvais :
if (is_colliding()):
queue_free()
Opérateurs booléens
Préférez les versions en anglais des opérateurs booléens, car elles sont les plus accessibles :
Utilisez
andau lieu de&&.Utilisez
orau lieu de||.Use
notinstead of!.
Vous pouvez également utiliser des parenthèses autour des opérateurs booléens pour éviter toute ambiguïté. Cela peut améliorer la lisibilité des longues expressions.
Bon :
if (foo and bar) or not baz:
print("condition is true")
Mauvais :
if foo && bar || !baz:
print("condition is true")
Espaces
Utilisez toujours un espace autour des opérateurs et après les virgules. Évitez également les espaces supplémentaires dans les références de dictionnaire et les appels de fonction. Une exception à cette règle concerne les déclarations de dictionnaire sur une seule ligne, où un espace doit être ajouté après l'accolade ouvrante et avant l'accolade fermante. Cela permet de distinguer plus facilement visuellement le dictionnaire d'un tableau, car les caractères [] et {} se ressemblent dans la plupart des polices.
Bon :
position.x = 5
position.y = target_position.y + 10
dict["key"] = 5
my_array = [4, 5, 6]
my_dictionary = { key = "value" }
print("foo")
Mauvais :
position.x=5
position.y = mpos.y+10
dict ["key"] = 5
myarray = [4,5,6]
my_dictionary = {key = "value"}
print ("foo")
Ne pas utiliser d'espaces pour aligner verticalement les expressions :
x = 100
y = 100
velocity = 500
Guillemets
Utilisez des guillemets doubles dans la mesure du possible, sauf si les guillemets simples peuvent réduire le nombre de caractères à échapper dans une chaîne de caractères donnée. Voir l'exemple ci-dessous :
# Normal string.
print("hello world")
# Use double quotes as usual to avoid escapes.
print("hello 'world'")
# Use single quotes as an exception to the rule to avoid escapes.
print('hello "world"')
# Both quote styles would require 2 escapes; prefer double quotes if it's a tie.
print("'hello' \"world\"")
Nombres
N'omettez pas le zéro de tête ou de queue dans les nombres à virgule flottante. Sinon, cela les rend moins lisibles et plus difficiles à distinguer des nombres entiers d'un seul coup d'œil.
Bon :
var float_number = 0.234
var other_float_number = 13.0
Mauvais :
var float_number = .234
var other_float_number = 13.
Utilisez des minuscules pour les lettres des nombres hexadécimaux, car leur hauteur réduite rend le nombre plus facile à lire.
Bon :
var hex_number = 0xfb8c0b
Mauvais :
var hex_number = 0xFB8C0B
Profitez des underscores de GDScript dans les littéraux pour rendre les grands nombres plus lisibles.
Bon :
var large_number = 1_234_567_890
var large_hex_number = 0xffff_f8f8_0000
var large_bin_number = 0b1101_0010_1010
# Numbers lower than 1000000 generally don't need separators.
var small_number = 12345
Mauvais :
var large_number = 1234567890
var large_hex_number = 0xfffff8f80000
var large_bin_number = 0b110100101010
# Numbers lower than 1000000 generally don't need separators.
var small_number = 12_345
Conventions de nommage
These naming conventions follow the Godot Engine style. Breaking these will make your code clash with the built-in naming conventions, leading to inconsistent code. As a summary table:
Type |
Convention |
Exemple |
|---|---|---|
Nom de fichier |
snake_case |
|
Class names |
PascalCase |
|
Node names |
PascalCase |
|
Fonctions |
snake_case |
|
Variables |
snake_case |
|
Signaux |
snake_case |
|
Constantes |
CONSTANT_CASE |
|
Enum names |
PascalCase |
|
Enum members |
CONSTANT_CASE |
|
Nom de fichier
Utilisez snake_case pour les noms de fichiers. Pour les classes nommées, convertissez le nom de la classe de PascalCase en snake_case :
# This file should be saved as `weapon.gd`.
class_name Weapon
extends Node
# This file should be saved as `yaml_parser.gd`.
class_name YAMLParser
extends Object
Cela correspond à la façon dont les fichiers C++ sont nommés dans le code source de Godot. Cela permet également d'éviter les problèmes de sensibilité à la casse qui peuvent survenir lors de l'exportation d'un projet de Windows vers d'autres plateformes.
Classes et Nœuds
Utiliser le PascalCase pour les noms des classes et des nœuds :
extends CharacterBody3D
Utiliser aussi le PascalCase lorsque vous chargez une classe dans une constante ou une variable :
const Weapon = preload("res://weapon.gd")
Fonctions et Variables
Utiliser le snake_case pour nommer les fonctions et variables :
var particle_effect
func load_level():
Préfixer un seul trait de soulignement (_) aux méthodes virtuelles que l'usager doit redéfinir, les fonctions privées, et les variables privées :
var _counter = 0
func _recalculate_path():
Signaux
Utiliser le passé pour nommer les signaux :
signal door_opened
signal score_changed
Constantes et énumérations
Écrivez les constantes avec CONSTANT_CASE, c'est-à-dire en majuscules avec un trait de soulignement (_) pour séparer les mots :
const MAX_SPEED = 200
Utilisez PascalCase pour les énumération(enum) names et CONSTANT_CASE pour leurs membres, car ce sont des constantes :
enum Element {
EARTH,
WATER,
AIR,
FIRE,
}
Write enums with each item on its own line. This allows adding documentation comments above each item more easily, and also makes for cleaner diffs in version control when items are added or removed.
Bon :
enum Element {
EARTH,
WATER,
AIR,
FIRE,
}
Mauvais :
enum Element { EARTH, WATER, AIR, FIRE }
Ordre du code
This section focuses on code order. For formatting, see Formatage. For naming conventions, see Conventions de nommage.
Nous suggérons d'organiser le code GDScript de cette manière :
01. @tool
02. class_name
03. extends
04. ## docstring
05. signals
06. enums
07. constants
08. @export variables
09. public variables
10. private variables
11. @onready variables
12. optional built-in virtual _init method
13. optional built-in virtual _enter_tree() method
14. built-in virtual _ready method
15. remaining built-in virtual methods
16. public methods
17. private methods
18. subclasses
Nous avons optimisé l'ordre pour rendre le code plus simple à lire de haut en bas, afin d'aider les développeurs à comprendre comment le code fonctionne la première fois qu'ils le lisent, et pour éviter les erreurs liées à l'ordre de déclaration des variables.
Cet ordre du code suit quatre règles générales :
Les propriétés et signaux viennent en premier, suivis des méthodes.
Publique vient avant privé.
Les rappels(callbacks) virtuels précèdent l'interface de la classe.
Les fonctions de construction et d'initialisation de l'objet,
_initet_ready, viennent avant les fonctions qui modifient l'objet à l'exécution.
Déclaration de classe
Si le code est destiné à être exécuté dans l'éditeur, utilisez l'annotation ``@tool``sur la première ligne du script.
Suivi de class_name si nécessaire. Vous pouvez transformer un fichier GDScript en un type global dans votre projet à l'aide de cette fonctionnalité. Pour plus d'informations, voir Référence GDScript.
Ensuite, ajoutez le mot-clé extends si la classe étend un type intégré.
Ensuite, vous devriez avoir les commentaires de documentation facultatifs de la classe <doc_gdscript_documentation_comments>. Vous pouvez l'utiliser pour expliquer le rôle de votre classe à vos coéquipiers, son fonctionnement et la manière dont les autres développeurs devraient l'utiliser, par exemple.
class_name MyNode
extends Node
## A brief description of the class's role and functionality.
##
## The description of the script, what it can do,
## and any further detail.
Signaux et propriétés
Écrivez les déclarations de signaux, suivies des propriétés, c'est-à-dire les variables membres, après la docstring.
Les énumérations doivent venir après les signaux, car vous pouvez les utiliser comme indices d’exportation pour les autres propriétés.
Ensuite, écrivez les constantes, les variables exportées puis les variables publiques, privées et onready, dans cet ordre.
signal player_spawned(position)
enum Jobs {
KNIGHT,
WIZARD,
ROGUE,
HEALER,
SHAMAN,
}
const MAX_LIVES = 3
@export var job: Jobs = Jobs.KNIGHT
@export var max_health = 50
@export var attack = 5
var health = max_health:
set(new_health):
health = new_health
var _speed = 300.0
@onready var sword = get_node("Sword")
@onready var gun = get_node("Gun")
Note
GDScript évalue les variables @onready juste avant l'appel _ready. Vous pouvez l'utiliser pour mettre en cache les dépendances des nœuds, c'est-à-dire pour obtenir les nœuds enfants de la scène sur lesquels votre classe s'appuie. C'est ce que montre l'exemple ci-dessus.
Variables membres
Ne déclarez pas les variables membres si elles ne sont utilisées que localement dans une méthode, car cela rend le code plus difficile à suivre. Déclarez-les plutôt comme des variables locales dans le corps de la méthode.
Variables locales
Déclarez les variables locales le plus près possible de leur première utilisation. Il est ainsi plus facile de suivre le code, sans avoir à trop le faire défiler pour retrouver l'endroit où la variable a été déclarée.
Méthodes et fonctions statiques
Après les propriétés de la classe viennent les méthodes.
Commencez avec la méthode de rappel _init (), que le moteur appellera lors de la création de l'objet en mémoire. Continuez avec la méthode de rappel _ready (), que Godot appelle quand il ajoute un nœud à l'arbre des scènes.
Ces fonctions doivent apparaître en premier car elles indiquent comment l'objet est initialisé.
D'autres méthodes de rappel virtuelles intégrées, comme _unhandled_input() et _physics_process, doivent venir ensuite. Celles-ci contrôlent la boucle principale de l'objet et les interactions avec le moteur de jeu.
Le reste de l'interface de la classe, les méthodes publiques et privées, viennent ensuite dans cet ordre.
func _init():
add_to_group("state_machine")
func _ready():
state_changed.connect(_on_state_changed)
_state.enter()
func _unhandled_input(event):
_state.unhandled_input(event)
func transition_to(target_state_path, msg={}):
if not has_node(target_state_path):
return
var target_state = get_node(target_state_path)
assert(target_state.is_composite == false)
_state.exit()
self._state = target_state
_state.enter(msg)
Events.player_state_changed.emit(_state.name)
func _on_state_changed(previous, new):
print("state changed")
state_changed.emit()
Typage statique
GDScript supports optional static typing.
Types déclarés
Pour déclarer le type d'une variable, utilisez <variable>: <type> :
var health: int = 0
Pour déclarer le type de retour d'une fonction, utilisez -> <type> :
func heal(amount: int) -> void:
Types inférés
Dans la plupart des cas, vous pouvez laisser le compilateur déduire le type en utilisant :=. Préférez := lorsque le type est écrit sur la même ligne que l'affectation, sinon préférez écrire le type explicitement.
Bon :
var health: int = 0 # The type can be int or float, and thus should be stated explicitly.
var direction := Vector3(1, 2, 3) # The type is clearly inferred as Vector3.
Incluez l'indication de type lorsque le type est ambigu et omettez l'indication de type lorsqu'elle est redondante.
Mauvais :
var health := 0 # Typed as int, but it could be that float was intended.
var direction: Vector3 = Vector3(1, 2, 3) # The type hint has redundant information.
# What type is this? It's not immediately clear to the reader, so it's bad.
var value := complex_function()
Dans certains cas, le type doit être indiqué explicitement, sinon le comportement ne sera pas celui attendu car le compilateur ne pourra utiliser que le type de retour de la fonction. Par exemple, get_node() ne peut pas déduire un type à moins que la scène ou le fichier du nœud ne soit chargé en mémoire. Dans ce cas, vous devez définir le type explicitement.
Bon :
@onready var health_bar: ProgressBar = get_node("UI/LifeBar")
Autrement, vous pouvez utiliser le mot-clé as pour transtyper le type de retour, et ce type sera utilisé pour inférer le type de la variable.
@onready var health_bar := get_node("UI/LifeBar") as ProgressBar
# health_bar will be typed as ProgressBar
Cette option est aussi considérée plus type-safe que la première.
Mauvais :
# The compiler can't infer the exact type and will use Node
# instead of ProgressBar.
@onready var health_bar := get_node("UI/LifeBar")
Espace de commentaires
Les commentaires classiques (
#) et les commentaires de documentation (##) doivent commencer par un espace, mais pas le code que vous commentez. De plus, les commentaires de région de code (#region/#endregion) doivent suivre cette syntaxe précise, ils ne doivent donc pas commencer par un espace.L'utilisation d'un espace pour les commentaires classiques et de documentation permet de différencier les commentaires de texte du code désactivé.
Bon :
Mauvais :
Note
Dans l'éditeur de script, pour activer ou désactiver les commentaires sur le code sélectionné, appuyez sur Ctrl + K. Cette fonction ajoute/supprime un seul signe
#avant le code sur les lignes sélectionnées.