Unity エディター拡張で追加したボタンから関数を呼び出す

以前UnityContextMenu Attrhttps://compota-soft.work/wp1/archives/1424ibute を使い、Inspector ウィンドウのコンポーネントの枠のプルダウンにメニューアイテム追加し、そこからメンバ関数を呼び出しました。

今回はエディター拡張(カスタムエディター)を使って Inspector ウィンドウに追加したボタンから関数を呼び出す実装手順を紹介します。
※ Unity は 2021.3.14f1 です。

エディター拡張とは

公式サイトの引用です。

Unity では独自のインスペクターと エディターウィンドウ、さらにインスペクターにプロパティーを表示する独自の Property Drawer を作成することができます。このセクションでは、これらの機能を使用する方法について説明します。

https://docs.unity3d.com/ja/2018.4/Manual/ExtendingTheEditor.html

エディターウィンドウは、EditorWindow を継承した独自のウィンドウです。 Sprite Editor のような特定の機能に特化したウィンドウを作成できます。

Property Drawer は、PropertyDrawer を継承することで Serialize 可能な特定のクラス(オブジェクト)の編集GUI をカスタマイズすることができます。
また、メンバ変数に付加できる Property Attribute に対応した独自の GUI を作成できます。

Editor を継承したカスタムエディターにより Inspector ウィンドウコンポーネント設定する GUI を変えられます。

このようにエディター拡張を用いることでエディターで利用可能な独自の GUI を作成し、編集効率を高めることができます。

エディター拡張用のスクリプトの置き場所

Unity では特殊なフォルダー名がいくつかあります。Unity プロジェクトの Assets フォルダーの下で用います。

たとえば画像や音楽などのリソースを読み込む関数 Resources.Load は、 Resources という名前のフォルダーの下に配置されているリソースを読み込みます。

エディター拡張用スクリプトEditor という名前のフォルダーの下に配置します。
フォルダー直下ではないサブフォルダーでも有効です。複数の Editor フォルダーを置くことができます。

Editor フォルダーに置かれたスクリプトは、エディターに機能を追加するもので、ゲーム実行時(ランタイム)は利用されません

Unity Editor フォルダーは Assets 内の複数の場所に配置できます。

最小限のエディタ用スクリプト

Assets 内の任意の場所に Editor フォルダーを作成したら、その中にエディター用のスクリプト(C#)を作成します。
今回は自作コンポーネントの設定Inspector ウィンドウで編集する際の GUI を拡張エディタ―のカスタムエディターによってカスタマイズします。

ファイル名について

自作コンポーネントの名前MyComponent の場合、それに対応したエディター拡張のスクリプトの名前は MyComponentEditor.cs にすること、対応するコンポーネントの名前の後に Editor を付加することが慣例的です。

編集対象のコンポーネントのスクリプト

カスタムエディターで編集する対象のコンポーネント MyComponent.cs を作ります。
これはエディター拡張スクリプトではなく、その編集対象のコンポーネントなので Editor フォルダーには置きません

using UnityEngine;

/// <summary>
/// エディター拡張(カスタムエディター)を学習するためのサンプルのコンポーネントです。
/// ./Editor/MyComponentEditor.cs により Inspector ウィンドウ内での設定画面をカスタマイズします。
/// </summary>
public class MyComponent : MonoBehaviour
{

    // カスタムエディターで編集するメンバ変数です。
    public int IntValue = 0;

    // カスタムエディターのボタンから呼び出される関数です。
    // メンバ変数 IntValue の現在の値をログ出力します。
    public void LogIntValue()
    {
        Debug.Log("MyComponent IntValue = " + IntValue);
    }
}

この MyComponent という自作コンポーネントをエディター拡張をしないで Inspector ウィンドウで表示すると次のようになります。

カスタムエディターを追加する前の MyComponent コンポーネントの Inspector ウィンドウ設定画面

エディター拡張用スクリプトの作成

作成した自作コンポーネント MyComponent を編集するために Inspector ウィンドウに表示する GUI をカスタムエディターによって変更します。
このスクリプトはエディター拡張用なので Editor フォルダーに置きます。

今回は IntValue をスライダーで設定できるように変更し、ログ出力関数を呼び出すボタンを追加します。

using UnityEngine;
using UnityEditor; // UnityEditor 名前空間を使うため

/// <summary>
/// MyComponent コンポーネントの Inspector ウィンドウでの編集画面をカスタマイズするカスタムエディター
/// </summary>
[CustomEditor(typeof(MyComponent))]  // 編集対象が MyComponent クラスであることを表す
public class MyComponentEditor : Editor // Editor を継承
{
    /// <summary>
    /// 編集対象の MyComponent オブジェクトです。
    /// </summary>
    MyComponent myComponent;

    /// <summary>
    /// MyComponent メンバ変数 IntValue に対応した編集用プロパティ
    /// </summary>
    SerializedProperty intValueProp;

    private void OnEnable()
    {
        // 編集対象のオブジェクトをキャストして保持します。
        myComponent = target as MyComponent;
        // MyComponent メンバ変数名からそのメンバ変数に対応した編集用プロパティを取得します。
        intValueProp = serializedObject.FindProperty("IntValue");   
    }

    public override void OnInspectorGUI()
    {
        // 各 SerializedProperty の情報を更新します。 OnInspectorGUI イベント関数内の最初の処理です。
        serializedObject.Update();

        // Inspector ウィンドウに GUI を表示する処理
        EditorGUILayout.IntSlider(intValueProp, 0, 100, new GUIContent("IntValue"));

        if (GUILayout.Button("IntValue ログ出力ボタン"))
        {
            myComponent.LogIntValue();
        }

        // 各 SerializedProperty に今回の変更を適用します。 OnInspectorGUI イベント関数内の最後の処理です。
        serializedObject.ApplyModifiedProperties();
    }
}

これにより、先ほどの標準の Inspector ウィンドウのコンポーネント設定画面が次のように変化しました。

カスタムエディターを追加した後の MyComponent コンポーネントの Inspector ウィンドウ設定画面

MyComponent の IntValue はテキスト以外にスライダーでも変更できるようにカスタマイズされました。
下側に追加されたボタンを押すと MyComponent の LogIntValue メンバ関数が呼び出され、現在の IntValue の値が Console ウィンドウにログ出力されました。

Unity カスタムエディターによって Inspector ウィンドウ内の MyComponent コンポーネントの編集画面を改造した様子

既定の編集画面の後にボタンだけ追加したい場合

今回は IntValue だけが編集対象でしたが、たくさんのメンバ変数があった場合、それぞれに GUI 表示の処理を書くのは大変です。
通常の編集画面のあとにボタンだけ追加したい場合base.OnInspectorGUI() を利用します。
base は継承元のクラスを指すため、この場合は Editor クラスの OnInspectorGUI() 関数を呼び出し、既定の編集画面を表示します。

    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI(); // デフォルトの編集画面の処理

        if (GUILayout.Button("IntValue ログ出力ボタン"))
        {
            myComponent.LogIntValue();
        }
    }

int 型の編集 GUIデフォルトのものに戻り、その後でボタンが表示されています。

カスタムエディターを追加した後の MyComponent コンポーネントの Inspector ウィンドウ設定画面(base.OnInspectorGUI を使用)

メンバ変数ごとに既定の GUI で編集したい場合

メンバ変数がたくさんあって、その一部だけ GUI を変えたい場合、カスタマイズしない他のメンバ変数たちは、PropertyField 関数を呼ぶだけでメンバ変数単位で既定の GUI で編集できます。

    public override void OnInspectorGUI()
    {
        // 各 SerializedProperty の情報を更新します。 OnInspectorGUI イベント関数内の最初の処理です。
        serializedObject.Update();

        // Inspector ウィンドウに GUI を表示する処理
        EditorGUILayout.PropertyField(intValueProp, new GUIContent("IntValue"));    // 型に応じた既定の編集 GUI を表示します。

        if (GUILayout.Button("IntValue ログ出力ボタン"))
        {
            myComponent.LogIntValue();
        }

        // 各 SerializedProperty に今回の変更を適用します。 OnInspectorGUI イベント関数内の最後の処理です。
        serializedObject.ApplyModifiedProperties();
    }

メンバ変数単位なので、先ほどの base.InspectorGUI() よりも、粒度の細かい設定画面のカスタマイズができます。
見た目は先ほどと変わりません。

カスタムエディターを追加した後の MyComponent コンポーネントの Inspector ウィンドウ設定画面(PropertyField をメンバ変数ごとに使用)

まとめ

今回は、エディター拡張(カスタムエディター)を使って Inspector ウィンドウのコンポーネント編集画面の GUI をカスタマイズする具体例を紹介しました。
エディター拡張についてはたくさんの機能があるので、これからも必要に応じて調べたことを紹介していきます。

参照サイト Thank You!

コメント

Ads Blocker Image Powered by Code Help Pro

お願い - Ads Blocker Detected

このサイトは広告を掲載して運営しています。

ポップアップを閉じて閲覧できますが、よろしければ

このサイト内の広告を非表示にする拡張機能をオフにしていただけませんか?

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

We have detected that you are using extensions to block ads. Please support us by disabling these ads blocker.

タイトルとURLをコピーしました