mcpField
A
addon-development

addon-development

github.com/jame581開発889165 回インストール5 日前に更新
リポジトリ

addon-development について

Godot 4.3以降でGDScriptまたはC#のエディタープラグインを作るためのスキルです。構成、エディター拡張、ライフサイクル管理、テストを扱います。

主な機能

  1. 01プラグインの構成と設定
  2. 02エディター用スクリプトとライフサイクル
  3. 03カスタムノード、インスペクター、ドック
  4. 04リソースエディターと3Dギズモ
  5. 05プラグインのテストと再読み込み

活用シーン

  1. 01エディターにカスタムノード型を追加
  2. 02プロパティ専用のインスペクター UIを作成
  3. 03プロジェクトツール用のドックを構築
  4. 04操作可能な3D編集ハンドルを追加

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/jame581/godotprompter --skill addon-development

インストール後、Claude Code で/addon-developmentを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
dock-panels.md
gizmos-deep-dive.md
inspector-plugins.md
testing-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ノード追加ダイアログに表示される名前
baseGodot の基底クラス名を表す文字列
scriptGDScript / C# のスクリプトリソース
iconTexture2D。通常は 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"

フィールドの説明:

KeyTypeDescription
nameStringプロジェクト設定 → プラグインに表示される名前
descriptionStringプラグインパネルに表示される簡単な説明
authorString作者名または組織名
versionStringセマンティックバージョン文字列(例:"1.2.0")
scriptStringメインの 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 で囲んでいる

コメント