addon-development について
Godot 4.3以降でGDScriptまたはC#のエディタープラグインを作るためのスキルです。構成、エディター拡張、ライフサイクル管理、テストを扱います。
主な機能
- 01プラグインの構成と設定
- 02エディター用スクリプトとライフサイクル
- 03カスタムノード、インスペクター、ドック
- 04リソースエディターと3Dギズモ
- 05プラグインのテストと再読み込み
活用シーン
- 01エディターにカスタムノード型を追加
- 02プロパティ専用のインスペクター UIを作成
- 03プロジェクトツール用のドックを構築
- 04操作可能な3D編集ハンドルを追加
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ jame581/ godotprompter --skill addon-developmentインストール後、Claude Code で/addon-developmentを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/dock-panels.mdgizmos-deep-dive.mdinspector-plugins.mdtesting-plugins.md詳細
Godot 4.3+ でのアドオン開発
エディタープラグインは、カスタムノード型、インスペクターパネル、ドックウィジェット、3D ギズモ、ツールバーボタンなど、Godot エディター自体を拡張します。すべての例は、非推奨 API を使用せず Godot 4.3+ を対象としています。
関連スキル: カスタム Resource エディターには resource-pattern、エディターパネルの UI には godot-ui、C# プラグイン開発には csharp-godot を参照してください。
1. プラグインの構造
すべてのプラグインは、プロジェクトルートの addons/ 内に配置します。Godot は plugin.cfg ファイルを検索してプラグインを検出します。
res://
└── addons/
└── my_plugin/
├── plugin.cfg # required — plugin metadata
├── plugin.gd # main EditorPlugin script (named in plugin.cfg)
├── my_inspector.gd # optional — EditorInspectorPlugin
├── my_dock.tscn # optional — dock panel scene
└── icons/
└── my_node.svg # optional — custom node icons
plugin.cfg は通常の INI ファイルです。Godot は addons/ を検索するときにこのファイルを読み込みます。script キーには、プラグインフォルダーからの相対パスでメインのプラグインスクリプトを指定する必要があります。
プラグインを有効にするには、プロジェクト → プロジェクト設定 → プラグインを開き、プラグイン名の横にあるチェックボックスをオンにします。
2. @tool アノテーション
@tool を付けると、GDScript(またはその C# 相当のスクリプト)が実行時だけでなくエディタープロセス内でも実行されます。これがない場合、スクリプトはゲームの実行中にのみ動作します。
GDScript
@tool
extends Sprite2D
# Engine.is_editor_hint() is true when running inside the editor,
# false during a running game. Use it to guard editor-only logic.
func _process(delta: float) -> void:
if Engine.is_editor_hint():
# This block runs in the editor viewport — safe to call editor APIs.
update_configuration_warnings()
else:
# Normal game logic here.
pass
# _get_configuration_warnings() returns an array of strings shown as
# yellow warning icons on the node in the Scene panel.
func _get_configuration_warnings() -> PackedStringArray:
var warnings := PackedStringArray()
if texture == null:
warnings.append("Texture is not set. Assign a Texture2D in the Inspector.")
return warnings
C#
using Godot;
[Tool]
public partial class MyToolSprite : Sprite2D
{
public override void _Process(double delta)
{
if (Engine.IsEditorHint())
{
// Editor-only logic. EditorInterface and other GodotSharpEditor types
// exist only in the editor build — wrap them in #if TOOLS.
UpdateConfigurationWarnings();
}
else
{
// Normal game logic.
}
}
public override string[] _GetConfigurationWarnings()
{
if (Texture == null)
return new[] { "Texture is not set. Assign a Texture2D in the Inspector." };
return System.Array.Empty<string>();
}
}
TOOLSはエディター用ビルドでのみ定義されるため、#if TOOLSによってエクスポートしたゲームからクラスが除外されます。エディター専用クラス(EditorPlugin、インスペクタープラグインなど)には使用してください。ゲーム内でも実行される[Tool]ノードには使用しないでください。エクスポートには、プリセットのフィルターで除外されない限り、ほかのスクリプトと同様に@toolスクリプトも含まれます。
主なルール:
- エディターへのアクセスが必要なすべてのスクリプトの先頭に、
@tool/[Tool]を付けます。 - シーンの読み込みが完了する前に処理が始まってエディターがクラッシュしないよう、実行時専用のコードは必ず
Engine.is_editor_hint()でガードします。 - 警告の状態に影響する可能性があるプロパティが変更されたときは、必ず
update_configuration_warnings()を呼び出します。
3. EditorPlugin の基底クラス
メインのプラグインスクリプトは EditorPlugin を継承します。Godot はプラグインが有効になると _enter_tree() を呼び出し、無効になるかプロジェクトが閉じられると _exit_tree() を呼び出します。_enter_tree() で追加したものはすべて、_exit_tree() で削除する必要があります。
GDScript
# plugin.gd
@tool
extends EditorPlugin
func _enter_tree() -> void:
# Register a custom node type. The editor shows MyNode in the
# "Add Node" dialog under the chosen base class, with a custom icon.
add_custom_type(
"MyNode", # name shown in editor
"Node2D", # base class to extend
preload("res://addons/my_plugin/my_node.gd"),
preload("res://addons/my_plugin/icons/my_node.svg")
)
# Add a menu item under Project > Tools.
add_tool_menu_item("My Plugin Action", _on_tool_menu_item)
func _exit_tree() -> void:
remove_custom_type("MyNode")
remove_tool_menu_item("My Plugin Action")
func _on_tool_menu_item() -> void:
print("My Plugin Action triggered")
C#
// Plugin.cs
#if TOOLS
using Godot;
[Tool]
public partial class MyPlugin : EditorPlugin
{
public override void _EnterTree()
{
AddCustomType(
"MyNode",
"Node2D",
GD.Load<Script>("res://addons/my_plugin/MyNode.cs"),
GD.Load<Texture2D>("res://addons/my_plugin/icons/my_node.svg")
);
AddToolMenuItem("My Plugin Action", new Callable(this, MethodName.OnToolMenuAction));
}
public override void _ExitTree()
{
RemoveCustomType("MyNode");
RemoveToolMenuItem("My Plugin Action");
}
private void OnToolMenuAction()
{
GD.Print("My Plugin Action triggered");
}
}
#endif
add_custom_type のパラメーター:
| パラメーター | 説明 |
|---|---|
name | ノード追加ダイアログに表示される名前 |
base | Godot の基底クラス名を表す文字列 |
script | GDScript / C# のスクリプトリソース |
icon | Texture2D。通常は 16×16 の SVG |
add_tool_menu_item は、トップメニューバーのプロジェクト → ツールに項目を追加します。引数を取らない Callable を渡します。
未保存状態とスクリプトエディターの制御(Godot 4.7+)
Godot 4.7 では、ビルド/エクスポートツールに役立つファイル管理 API が追加されました。アクションを実行する前に未保存の作業がないか確認したり、外部ツールによって変更されたスクリプトを更新したりできます。
func _run_pre_build_check() -> void:
var unsaved_scenes := EditorInterface.get_unsaved_scenes() # PackedStringArray of scene paths
var script_editor := EditorInterface.get_script_editor()
var unsaved_files := script_editor.get_unsaved_files() # PackedStringArray of script paths
if not unsaved_scenes.is_empty() or not unsaved_files.is_empty():
push_warning("Unsaved work detected — save before building.")
script_editor.save_all_scripts() # saves every open script
script_editor.reload_open_files() # re-read files changed outside the editor
# Closes the tab, discarding unsaved changes; OK or ERR_FILE_NOT_FOUND.
var err := script_editor.close_file("res://addons/my_plugin/generated.gd")
#if TOOLS
private void RunPreBuildCheck()
{
string[] unsavedScenes = EditorInterface.Singleton.GetUnsavedScenes();
var scriptEditor = EditorInterface.Singleton.GetScriptEditor();
string[] unsavedFiles = scriptEditor.GetUnsavedFiles();
if (unsavedScenes.Length > 0 || unsavedFiles.Length > 0)
GD.PushWarning("Unsaved work detected — save before building.");
scriptEditor.SaveAllScripts();
scriptEditor.ReloadOpenFiles();
Error err = scriptEditor.CloseFile("res://addons/my_plugin/Generated.cs");
}
#endif
4. カスタムインスペクタープラグイン
特定の型のエクスポート済みプロパティにカスタムウィジェットを使用するには、メインの EditorPlugin から EditorInspectorPlugin を登録します。インスペクタープラグインでは、_can_handle をオーバーライドして対象を指定し、_parse_property(または _parse_begin)をオーバーライドしてカスタムウィジェットを挿入します。実際の UI には EditorProperty のサブクラスを組み合わせます。
GDScript と C# の完全なひな形(カスタムインスペクター + EditorProperty + 登録用の定型コード)については、references/inspector-plugins.md を参照してください。
Godot 4.7+: 静的メソッド
EditorInspector.create_default_inspector(filter_line_edit: LineEdit = null)は、エディターのインスペクタードックと同じ設定のインスペクターを返すため、プラグイン UI に埋め込めます。プロパティのライブフィルタリングにはLineEditを渡します(references/inspector-plugins.md を参照)。また、EditorContextMenuPluginのContextMenuSlotにCONTEXT_SLOT_INSPECTOR_PROPERTYが追加され、コンテキストメニュープラグインからインスペクタープロパティの右クリックメニューを拡張できるようになりました。_popup_menu()には[object ID, property name]が渡され、オプションのコールバックにはEditorPropertyが直接渡されます。
5. カスタムドックパネル
EditorPlugin._enter_tree から add_control_to_dock(slot, control) を呼び出して、エディターにカスタムドックを追加します。_exit_tree でコントロールを解放してください。プロジェクト全体で使うツールの UI(レベルブラウザー、アセットの概要、ビルドダッシュボードなど)に便利です。
GDScript と C# のドックのスキャフォールド全体については、references/dock-panels.md を参照してください。
6. カスタムリソースエディター
EditorResourcePicker を使うと、ツールチップとベース型フィルターを設定して、プロパティを特定の Resource サブクラスに制限できます。EditorResourcePreviewGenerator を使うと、FileSystem ドックやインスペクターに表示するリソースのカスタムサムネイルを作成できます。
GDScript と C# の
EditorResourcePickerおよびEditorResourcePreviewGeneratorのスキャフォールド全体については、references/inspector-plugins.md を参照してください。
7. ギズモ
EditorNode3DGizmoPlugin を使うと、エディター内の 3D ノードに視覚的なハンドルを追加できます。ワイヤーフレーム形状、ドラッグ可能なハンドル、回転リングなどを作成できます。インタラクティブな編集を実装するには、_init(マテリアル)、_get_gizmo_name、_has_gizmo、_redraw(線やハンドルの描画)、および _get_handle_value / _set_handle / _commit_handle を実装します。
ハンドルの確定時にアンドゥ/リドゥを連携させた、GDScript と C# のギズモプラグイン全体については、references/gizmos-deep-dive.md を参照してください。
Godot 4.7 以降:
_can_commit_handle_on_click() -> boolをオーバーライドすると(オーバーライドしない場合はfalseを返します)、ハンドルの最終位置が初期位置と同じ場合でも、ハンドル操作を確定できます。つまり、クリックのみでも確定できます。
8. プラグインのテスト
プラグインを再読み込みするには、プロジェクト設定 → プラグインでプラグインをオフにしてからオンにします。@tool スクリプトを保存すると自動的にホットリロードされますが、新しいクラスの登録やドックの変更には一連の再読み込みが必要です。print() / push_warning() / push_error() の出力先は出力パネルです。C# プラグインは先に再コンパイルする必要があります。「Unable to load addon script from path … This might be due to a code error in that script」というエラーは、通常、アセンブリのビルドに失敗したことを意味します。まず MSBuild パネルを確認してください。
再読み込みの手順(GDScript と C# の PluginReloader)、コンソール起動フラグ、ライフサイクルに関する注意点の表(孤立したドック、古いカスタム型、インスペクタープラグインの二重登録)については、references/testing-plugins.md を参照してください。
9. plugin.cfg の形式
plugin.cfg は、プラグインフォルダーのルートに配置するプレーンな INI ファイルです。[plugin] セクションの 5 つのフィールドはすべて必須です。いずれかが欠けている plugin.cfg はプラグイン一覧に表示されません。
[plugin]
name="My Plugin"
description="Adds MyNode, a custom inspector, and a dock panel to the editor."
author="Your Name"
version="1.0.0"
script="plugin.gd"
フィールドの説明:
| Key | Type | Description |
|---|---|---|
name | String | プロジェクト設定 → プラグインに表示される名前 |
description | String | プラグインパネルに表示される簡単な説明 |
author | String | 作者名または組織名 |
version | String | セマンティックバージョン文字列(例:"1.2.0") |
script | String | メインの EditorPlugin スクリプトへのパス。プラグインフォルダーからの相対パス |
Godot 4.x の
plugin.cfgに、ほかの標準キーはありません。依存関係の管理は外部(Asset Library や手動インストール手順など)で行います。
10. チェックリスト
-
addons/<plugin_name>/plugin.cfgが存在し、name、description、author、version、scriptが設定されている - メインスクリプトが
EditorPluginを継承し、@tool(GDScript)または#if TOOLS内の[Tool]で装飾されている -
_enter_tree()で登録したものはすべて_exit_tree()で登録解除されている - カスタムノード型には、対応するアイコン SVG とともに
add_custom_type/remove_custom_typeを使用している -
@toolスクリプトでは、エディター専用コードをEngine.is_editor_hint()でガードしている - ノードの設定が不正な場合、
_get_configuration_warnings()が空でない配列を返す - インスペクタープラグインで
_can_handleを実装し、意図しない型を処理しないようにしている -
_parse_propertyは、カスタムエディターが必要なプロパティに対してのみtrueを返す - ドックシーンに
Custom Minimum Sizeが設定され、デフォルトのドック幅でもパネルを使用できる - ドックの
Controlを_exit_tree()でqueue_free()により解放している -
EditorResourcePreviewGeneratorをEditorInterface.get_resource_previewer()経由で追加および削除している - ギズモプラグインで
_commit_handleを実装し、ハンドルのドラッグを取り消し可能にするため、渡されたEditorPluginのget_undo_redo()を使用している - 構造を変更するたびに、プラグインを完全に無効化してから有効化するサイクルでテストしている
- すべての
_enter_treeのセットアップ処理で、失敗を黙って無視せずpush_error()を使用している - C# プラグインスクリプトを
#if TOOLS/#endifで囲んでいる