Speedrunning le développement d'addons Godot avec JetBrains Rider : GDExtensions C++ natives et Editor Plugins
En bref
Cet article explique comment JetBrains Rider 2026.2 simplifie radicalement le développement d'addons pour Godot grâce à des templates clés en main, l'automatisation CMake et le débogage multi-langue simultané (C++ et GDScript). En levant les barrières de configuration manuelles de GDExtension et des pipelines d'assets, l'IDE permet aux créateurs d'outils de se concentrer sur l'essentiel. Enfin, l'intégration du SDK de horizOn offre une solution robuste pour connecter ces extensions à un backend évolutif sans effort d'infrastructure.
Building a custom Godot editor plugin or a native C++ GDExtension usually begins with a sudden, painful realization: you've spent three hours configuring SCons compile scripts, fighting headless compiler flags, and parsing ambiguous cross-compilation errors instead of writing your plugin's actual logic. While Godot 4's architecture has unlocked incredible potential for extensions, the developer experience has historically felt like configuring a server rack with a toothpick. With the launch of the new Godot Asset Store, IDE providers are finally treating addon development as a first-class citizen.
Le développement d'un editor plugin Godot personnalisé ou d'une GDExtension C++ native commence généralement par un constat soudain et douloureux : vous venez de passer trois heures à configurer des scripts de compilation SCons, à vous battre avec des flags de compilateur headless et à analyser des erreurs de cross-compilation ambiguës au lieu d'écrire la logique réelle de votre plugin. Bien que l'architecture de Godot 4 ait libéré un potentiel incroyable pour les extensions, la developer experience a historiquement ressemblé à la configuration d'une baie serveur avec un cure-dent. Avec le lancement du nouvel Godot Asset Store, les fournisseurs d'IDE traitent enfin le développement d'addons comme un citoyen de première classe.
JetBrains Rider 2026.2 entre officiellement dans l'arène comme l'un des premiers grands fournisseurs d'IDE à proposer des templates dédiés, l'automatisation CMake et le débogage multi-langue pour le Godot Asset Store. Pour les développeurs indépendants et les ingénieurs d'outils d'équipe, cela signifie la fin de l'enfer de la configuration du boilerplate et le début du prototypage rapide d'outils. En réduisant les temps de configuration à un wizard en un seul clic, la barrière pour étendre l'interface de l'éditeur principal de Godot n'a jamais été aussi basse.
Le goulot d'étranglement de GDExtension : pourquoi l'outillage Godot faisait mal
Sous le capot, Godot 4 utilise GDExtension pour permettre aux développeurs d'écrire du code C++ ou Rust haute performance qui s'interface directement avec les structures de base du moteur sans recompiler l'intégralité de celui-ci. Il y parvient en chargeant des bibliothèques dynamiques — telles que .dll sur Windows, .so sur Linux et .dylib sur macOS — et en les mappant sur des interfaces GDScript. Cependant, configurer cela manuellement nécessite de cloner le dépôt de bindings godot-cpp, de faire correspondre le header exact de la version du moteur, d'écrire des scripts SCons ou CMake personnalisés et de configurer un fichier .gdextension pour mapper les chemins de bibliothèque sur cinq plateformes cibles différentes.
Pire encore, le débogage de ces binaires natifs a la réputation d'être particulièrement sujet aux plantages. Un workflow de dépannage typique consiste à lancer l'éditeur Godot sous un debugger distinct (comme GDB or LLDB), à définir des points d'arrêt dans un éditeur externe et à croiser les doigts pour qu'un hot-reload ne fasse pas paniquer le thread principal du moteur et ne provoque pas un plantage brutal. Lorsque les développeurs conçoivent des outils personnalisés — en particulier des synchronisateurs de bases de données complexes, des interfaces de netcode à faible latence ou des pipelines d'assets — cette friction détruit complètement la productivité.
Rider 2026.2 : analyse de la nouvelle toolchain d'addons
Des templates de projet prêts à l'emploi
Rider 2026.2 propose des templates dédiés basés sur des wizards couvrant toute la gamme des formats d'extension Godot. Vous n'avez plus besoin de cloner des dépôts de boilerplate ou de copier-coller des structures de dossiers à partir d'anciens projets. Au lieu de cela, l'IDE génère un dépôt propre et structuré pour les editor plugins GDScript, les extensions C# ou les GDExtensions C++, préconfiguré avec tout le nécessaire, du plugin.cfg aux dossiers de build cibles. Cela évite des heures de configuration et élimine la cause la plus fréquente d'échecs au démarrage : des chemins de dossiers incorrects dans les fichiers manifestes.
Intégration CMake native pour le C++
Historiquement, les bindings C++ de Godot privilégiaient fortement SCons comme système de build. SCons est puissant, mais ses fichiers de configuration basés sur Python sont notoirement opaques, manquent d'autocomplétion dans l'IDE et compliquent l'intégration CI/CD. Rider 2026.2 introduit une intégration CMake native et robuste pour les projets GDExtension. Lorsque vous créez un addon GDExtension, Rider génère automatiquement un fichier CMakeLists.txt propre qui lie la bibliothèque de bindings principale godot-cpp à votre code source personnalisé. Cela vous permet d'utiliser le puissant moteur C++ de Rider pour la navigation dans le code, le refactoring et l'analyse statique sans aucune configuration supplémentaire.
Débogage double langage dans une seule session
C'est le joyau de cette mise à jour. Les développeurs qui écrivent des outils Godot haute performance se limitent rarement à un seul langage. Une architecture standard utilise du C++ haute performance pour le traitement intensif des données ou les calculs mathématiques complexes, et un fichier GDScript léger pour le dock GUI ou le panneau de l'UI de l'éditeur. Déboguer cette architecture hybride impliquait d'utiliser des outils distincts pour le C++ et le GDScript. Rider 2026.2 génère automatiquement des configurations d'exécution unifiées. Il vous suffit de cliquer sur un seul bouton "Debug" pour que Rider lance l'éditeur Godot, s'attache à son processus et suive l'exécution simultanément en GDScript et en C++. Un point d'arrêt dans le GDScript de votre UI se déclencera, et lorsque vous entrerez dans une fonction native C++, Rider passera de manière transparente au debugger C++ sans interrompre la session.
Architecture de dossiers prête pour la publication
Le nouveau Godot Asset Store impose des structures de dossiers et des exigences de packaging strictes pour éviter que les addons n'interfèrent avec les namespaces des uns et des autres. Les templates de Rider appliquent ces recommandations dès le premier jour. En séparant les fichiers de runtime des composants GUI réservés à l'éditeur, l'IDE garantit que lorsque vous générez un build, il est immédiatement prêt à être mis en ligne sur le store, transformant les erreurs de packaging d'un mal de crâne fréquent en un non-événement automatisé.
Au cœur du cycle de vie de GDExtension : concevoir le backend C++
Pour comprendre la valeur de l'automatisation de Rider, nous devons examiner ce qu'un projet GDExtension requiert réellement au niveau du code. Dans une GDExtension standard, vous devez définir un initialiseur de bibliothèque comme point d'entrée, enregistrer vos types de classes personnalisés dans la ClassDB de Godot et nettoyer soigneusement les allocations lorsque le module est désinitialisé. Les headers et fichiers sources C++ suivants représentent le boilerplate minimal requis pour créer un nœud natif personnalisé — dans ce cas, un gestionnaire de télémétrie haute performance.
// horizon_telemetry_node.h
#ifndef HORIZON_TELEMETRY_NODE_H
#define HORIZON_TELEMETRY_NODE_H
#include <godot_cpp/classes/node.hpp>
#include <godot_cpp/core/class_db.hpp>
namespace godot {
class HorizonTelemetryNode : public Node {
GDCLASS(HorizonTelemetryNode, Node);
private:
String session_id;
int event_count;
protected:
static void _bind_methods();
public:
HorizonTelemetryNode();
~HorizonTelemetryNode();
void initialize_telemetry(const String &p_session_id);
void track_event(const String &p_event_name);
String get_session_id() const;
};
}
#endif // HORIZON_TELEMETRY_NODE_H
Ensuite, nous implémentons le comportement principal. Dans le fichier d'implémentation, nous enregistrons nos méthodes dans _bind_methods() pour nous assurer que le moteur de réflexion au runtime de Godot peut y accéder.
// horizon_telemetry_node.cpp
#include "horizon_telemetry_node.h"
#include <godot_cpp/variant/utility_functions.hpp>
using namespace godot;
void HorizonTelemetryNode::_bind_methods() {
ClassDB::bind_method(D_METHOD("initialize_telemetry", "session_id"), &HorizonTelemetryNode::initialize_telemetry);
ClassDB::bind_method(D_METHOD("track_event", "event_name"), &HorizonTelemetryNode::track_event);
ClassDB::bind_method(D_METHOD("get_session_id"), &HorizonTelemetryNode::get_session_id);
ADD_PROPERTY(PropertyInfo(Variant::STRING, "session_id"), "", "get_session_id");
}
HorizonTelemetryNode::HorizonTelemetryNode() {
event_count = 0;
session_id = "";
}
HorizonTelemetryNode::~HorizonTelemetryNode() {
// Clean up memory safely here
}
void HorizonTelemetryNode::initialize_telemetry(const String &p_session_id) {
session_id = p_session_id;
UtilityFunctions::print("Telemetry initialized for session: ", session_id);
}
void HorizonTelemetryNode::track_event(const String &p_event_name) {
event_count++;
UtilityFunctions::print("Event tracked: ", p_event_name, " (Total: ", event_count, ")");
}
String HorizonTelemetryNode::get_session_id() const {
return session_id;
}
Enfin, nous devons indiquer à Godot comment charger notre module à l'aide d'une fonction d'initialisation. Ce fichier register_types sert de point d'entrée principal pour la bibliothèque, connecté via le système de chargement de GDExtension.
// register_types.cpp
#include "register_types.h"
#include "horizon_telemetry_node.h"
#include <gdextension_interface.h>
#include <godot_cpp/core/defs.hpp>
#include <godot_cpp/godot.hpp>
using namespace godot;
void initialize_horizon_plugin_module(ModuleInitializationLevel p_level) {
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
return;
}
ClassDB::register_class<HorizonTelemetryNode>();
}
void uninitialize_horizon_plugin_module(ModuleInitializationLevel p_level) {
if (p_level != MODULE_INITIALIZATION_LEVEL_SCENE) {
return;
}
}
extern "C" {
// Initialization entry point called by Godot.
GDExtensionBool GDE_EXPORT horizon_plugin_library_init(GDExtensionInterfaceGetProcAddress p_get_proc_address, const GDExtensionClassLibraryPtr p_library, GDExtensionInitialization *r_initialization) {
godot::GDExtensionBinding::InitObject init_obj(p_get_proc_address, p_library, r_initialization);
init_obj.register_initializer(initialize_horizon_plugin_module);
init_obj.register_terminator(uninitialize_horizon_plugin_module);
init_obj.set_minimum_library_initialization_level(MODULE_INITIALIZATION_LEVEL_SCENE);
return init_obj.init();
}
}
Développer des Editor Plugins : la pipeline GDScript
Alors que GDExtension gère le backend C++ haute performance, l'UI de votre addon Godot — comme l'ajout d'un panneau personnalisé dans le dock inférieur ou la création de nœuds d'inspecteur personnalisés — est généralement écrite en GDScript en utilisant l'annotation @tool. La directive @tool indique à Godot que ce script doit s'exécuter directement dans l'instance de l'éditeur en cours d'exécution, et pas seulement lorsque le jeu est lancé.
L'écriture de scripts tool nécessite une gestion propre du cycle de vie. Les fonctions _enter_tree() et _exit_tree() agissent comme les constructeurs et destructeurs de vos intégrations d'éditeur. Ne pas nettoyer les nœuds d'UI personnalisés lors du déchargement de l'éditeur entraînera la présence de nœuds GUI orphelins obsolètes qui encombreront l'espace mémoire de l'éditeur, ce qui finit par déclencher des plantages à la fermeture.
# horizon_editor_plugin.gd
@tool
extends EditorPlugin
const PLUGIN_NAME = "HorizonBackendHelper"
var dock: Control
func _enter_tree() -> void {
# Initialize the dock UI from our pre-packed scene
dock = preload("res://addons/horizon_plugin/dock.tscn").instantiate()
# Add the main panel to the editor dock on the upper-right slot
add_control_to_dock(DOCK_SLOT_LEFT_UR, dock)
# Register our custom backend node so developers can add it in the scene tree
add_custom_type(
"HorizonClientNode",
"Node",
preload("res://addons/horizon_plugin/horizon_client_node.gd"),
preload("res://addons/horizon_plugin/icon.png")
)
print("Plugin ", PLUGIN_NAME, " successfully initialized in editor.")
func _exit_tree() -> void {
# Clean up dock and custom types to prevent editor memory leaks
if dock:
remove_control_from_docks(dock)
dock.queue_free()
remove_custom_type("HorizonClientNode")
print("Plugin ", PLUGIN_NAME, " cleaned up.")
Le défi de la connectivité : intégrer des backends distants
Lors de la création d'editor plugins ou de GDExtensions, votre outil n'est souvent aussi puissant que les services backend avec lesquels il s'interface. Par exemple, si vous concevez un panneau d'administration pour un jeu indépendant, un éditeur de niveau distant ou un outil de suivi de télémétrie in-engine, votre plugin doit communiquer avec des bases de données, gérer les identités des développeurs ou des joueurs et synchroniser des états distants. Implémenter cela vous-même signifie concevoir un service web sécurisé et personnalisé. Vous devez configurer un serveur privé virtuel, mettre en place une API gateway, déployer une base de données, écrire des modèles d'authentification utilisateur personnalisés et gérer la rotation des certificats SSL/TLS. Cela représente une surcharge d'ingénierie énorme qui peut facilement consommer 4 à 6 semaines de développement dédié avant même que votre plugin ne puisse communiquer avec une base de données.
Au lieu de canaliser l'énergie limitée de votre équipe dans la gestion d'une infrastructure backend brute, vous pouvez intégrer horizOn comme backend principal de votre moteur de jeu. horizOn fournit un SDK natif haute performance en C# et GDScript que vous pouvez brancher directement sur vos editor addons personnalisés. Plutôt que de passer des semaines à provisionner des bases de données et à écrire des gestionnaires WebSockets personnalisés, vous pouvez intégrer le client de horizOn dans votre projet et bénéficier instantanément d'une authentification sécurisée, d'un accès en temps réel aux bases de données et de la gestion des joueurs. En laissant la gestion lourde de l'infrastructure à horizOn, vous pouvez consacrer votre temps à peaufiner l'UX de votre addon et vos outils de gameplay, tout en sachant que votre backend s'adaptera de manière transparente à l'échelle lorsque vous publierez sur le store.
5 bonnes pratiques éprouvées pour le développement d'addons Godot
1. Isolation des namespaces via la structure des dossiers
Préfixez toujours vos dossiers et scripts d'addons avec un namespace unique sous res://addons/votre_nom_d_addon_unique/. Godot partage un namespace global plat unique pour toutes les classes personnalisées enregistrées via les directives @icon ou class_name. Si vous utilisez un nom de classe générique comme NetworkManager ou ConfigHelper, votre addon entrera en conflit avec le projet principal du développeur ou d'autres extensions tierces. Conservez tous vos scripts utilitaires strictement limités au répertoire de votre dossier unique.
2. Automatiser la compilation binaire et l'exclure du VCS
Gardez les binaires GDExtension lourds et compilés (.dll, .so, .dylib) hors de l'historique de votre dépôt Git principal. La taille du dépôt gonflera rapidement au fur et à mesure que vous recompilez des bibliothèques pendant le développement. Utilisez plutôt un .gitignore pour ignorer les répertoires de build et les dossiers de release, et configurez un pipeline CI/CD (comme GitHub Actions ou GitLab CI) à l'aide de scripts CMake automatisés pour builder les binaires cibles pour plusieurs plateformes, en ne les packageant que dans des fichiers zip de release.
3. Gérer la frontière GDScript-vers-C++ avec précaution
Faites attention à la façon dont la mémoire est gérée lors du passage de variables à travers la frontière entre les langages. GDScript gère automatiquement le cycle de vie des classes dérivées de RefCounted (comme Resource), mais utilise une gestion manuelle de la mémoire pour les objets héritant d' Object (comme les objets Node bruts). Dans votre code C++ GDExtension, utilisez toujours le wrapper intelligent Ref<T> de Godot pour les classes à comptage de références afin d'éviter les erreurs de double-free ou les fuites de mémoire. Pour les classes standard, effectuez un casting défensif en utilisant Object::cast_to<T>() et vérifiez les pointeurs nuls avant d'appeler des méthodes natives.
4. Privilégier les WebSockets et les connexions persistantes pour l'état en temps réel
Évitez d'utiliser le HTTP polling traditionnel pour les plugins qui nécessitent une synchronisation en temps réel, comme les systèmes d'éditeur partagés ou les outils de matchmaking backend. L'envoi répété de requêtes HTTP génère une surcharge de CPU élevée et déclenche d'importantes pénalités de rate-limiting sur les services backend. Au lieu de cela, vous devriez abandonner le HTTP polling au profit des WebSockets pour établir une connexion bidirectionnelle persistante. Cela réduit la latence d'environ 500 ms à des intervalles inférieurs à 10 ms et minimise la surcharge de données.
5. Concevoir des systèmes de fallback résilients pour les pipelines cloud distants
Si votre addon communique avec des serveurs cloud distants, ne laissez jamais une interruption du réseau figer le thread de l'éditeur Godot. Les requêtes web synchrones peuvent bloquer le processus principal de Godot, provoquant le blocage de l'éditeur. Utilisez toujours des callbacks asynchrones ou des thread pools pour maintenir la fluidité des réponses de l'UI. De plus, si vous concevez une intégration live-ops, étudiez comment concevoir des pipelines robustes en évaluant la campagne stop killing games par rapport aux fallbacks de serveur live ops. Cela garantit que votre outil repasse proprement en offline mode et maintient l'éditeur fonctionnel même lorsque les endpoints cloud sont complètement inaccessibles.
Conclusion : rationaliser votre pipeline d'outils Godot
JetBrains Rider 2026.2 transforme le développement d'addons Godot, passant d'un exercice complexe de configuration système à un workflow de développement rationalisé et productif. En automatisant le scaffolding de GDExtension, en fournissant une intégration CMake robuste et en offrant un débogage simultané de GDScript et C++, Rider élimine la fatigue de la configuration et vous permet de vous concentrer sur le code de magnifiques outils. Combiner les templates de développement de Rider avec une architecture backend évolutive et entièrement managée vous permet de concevoir des plugins connectés et haute performance sans la surcharge liée à l'ingénierie serveur manuelle.
Prêt à faire évoluer votre backend multiplayer ? Essayez horizOn gratuitement ou consultez la documentation API.
Source : JetBrains Rider apporte le support des addons du Godot Asset Store