Version: Unity 6.0 (6000.0)
言語 : 日本語
C# スクリプトを使用したカスタムエディターウィンドウの作成
Create a default Inspector

カスタムインスペクターの作成

バージョン: 2022.3+

MonoBehaviour と ScriptableObject に対してはデフォルトインスペクターがありますが、独自のクラス用にカスタムインスペクターの作成が求められる場合もあります。カスタムインスペクターは、以下の操作に役立ちます。

  • スクリプトのプロパティをよりユーザーが使いやすい表示にする。
  • プロパティを整理し、グループ化する。
  • ユーザーの選択で、UI の各セクションを表示または非表示にする。
  • 個々の設定やプロパティの意味について、追加情報を提供する。

例の概要

この例では、MonoBehaviour クラス用にカスタムインスペクターを作成します。C# スクリプトと UI Builder の両方を使用して UI を作成します。カスタムインスペクターには、カスタムプロパティドロワーもあります。

カスタムインスペクターには、メーカー、製造年、色、タイヤのリストなど、Car クラスのプロパティが表示されます。インスペクターは PropertyField コントロールを使用して Car クラスのプロパティを表示します。また、カスタムプロパティドロワーを使用して Tire クラスのプロパティを表示します。

この例で作成する完成したファイルは、こちらの GitHub リポジトリにあります。

必要な要件

このガイドは、Unity エディター、UI Toolkit、および C# スクリプトに精通している開発者を対象としています。始める前に、以下の点を理解しておいてください。

新しい MonoBehaviour の作成

カスタムインスペクターを作成するには、最初に MonoBehaviour から継承するカスタムクラスを定義します。カスタムクラスは、いくつかのプロパティを持つ単純な car を表します。

  1. Unity で、任意のテンプレートでプロジェクトを作成します。

  2. Project ウィンドウに、create-a-custom-inspector という名前のフォルダーを作成し、すべてのファイルを保存します。

  3. 以下のコンテンツで Car.cs という名前の C# スクリプトを作成します。

    using UnityEngine;
    
    public class Car : MonoBehaviour
    {
         public string m_Make = "Toyota";
         public int m_YearBuilt = 1980;
         public Color m_Color = Color.black;
    }
    
  4. シーン内に新しいゲームオブジェクトを作成し、Car スクリプトコンポーネントをそれにアタッチします。

    Car オブジェクトのデフォルトインスペクター
    Car オブジェクトのデフォルトインスペクター

カスタムインスペクタースクリプトの作成

任意のシリアライズされたオブジェクトのカスタムインスペクターを作成するには、Editor 基本クラスから派生したクラスを作成し、CustomEditor 属性をそのクラスに追加する必要があります。この属性によって、Unity はこのカスタムインスペクターがどのクラスを表しているのかを知ることができます。

ノート: カスタムインスペクタースクリプトは、Editor フォルダーまたはエディター専用のアセンブリ定義内に置く必要があります。これは、カスタムインスペクターの作成に不可欠な UnityEditor 名前空間に、これらの領域外からアクセスできないためです。これに従わずにスタンドアロンビルドを作成しようとすると、ビルドプロセスは失敗します。

  1. create-a-custom-inspector フォルダー内に Editor という名前のフォルダーを作成します。

  2. Editor フォルダー内に以下のコンテンツを含む Car_Inspector.cs という名前の C# スクリプトを作成します。

    using UnityEditor;
    using UnityEditor.UIElements;
    using UnityEngine.UIElements;
    
    [CustomEditor(typeof(Car))]
    public class Car_Inspector : Editor
    {
    }
    
  3. Car コンポーネントがアタッチされているゲームオブジェクトを選択します。デフォルトインスペクターが表示されます。

  4. デフォルトインスペクターを置き換えるには、Car_Inspector クラス内に、CreateInspectorGUI() をオーバーライドし、UI を含む新しいビジュアル要素を返す、以下のコードを追加します。

    public override VisualElement CreateInspectorGUI()
    {
         // Create a new VisualElement to be the root of our Inspector UI.
         VisualElement myInspector = new VisualElement();
    
         // Add a simple label.
         myInspector.Add(new Label("This is a custom Inspector"));
    
         // Return the finished Inspector UI.
         return myInspector;
    }
    
  5. Car コンポーネントがアタッチされているゲームオブジェクトを選択します。このインスペクターは、デフォルトインスペクターの代わりにラベル This is a custom Inspector を表示します。

    ラベル付きのカスタムインスペクター
    ラベル付きのカスタムインスペクター

UI Builder でカスタムインスペクター UI を作成する

UI Builder でカスタムインスペクター UI を作成し、C# スクリプトを使用して UXML ファイルから UI のロードとインスタンス化ができます。

  1. UI Builder を開くには、Window > UI Toolkit > UI Builder を選択します。

  2. File > **New ** を選択して、新しいビジュアルツリーアセットを作成します。

    ラベル付きのカスタムインスペクター
    ラベル付きのカスタムインスペクター
  3. UI Builder でエディター専用コントロールを有効にするには、Hierarchy ビューで <unsaved file>*.uxml を選択し、Editor Extension Authoring チェックボックスにチェックを入れます。

    ラベル付きのカスタムインスペクター
    ラベル付きのカスタムインスペクター
  4. ラベルコントロールを Library から Hierarchy にドラッグします。これにより、ビジュアルツリーにラベルコントコントロールが追加されます。

    ラベル付きのカスタムインスペクター
    ラベル付きのカスタムインスペクター
  5. ラベルコントロールの Inspector パネルで、ラベルのテキストを更新します。

    ラベル付きのカスタムインスペクター
    ラベル付きのカスタムインスペクター
  6. File > Save を選択し、ビジュアルツリーを Car_Inspector_UXML.uxml として Assets/create-a-custom-inspector フォルダーに保存します。

カスタムインスペクターで UXML を使用する

作成した UXML ファイルをカスタムインスペクター内で使用するには、ファイルをカスタムインスペクターに割り当て、CreateInspectorGUI() 関数内でロードして複製し、ビジュアルツリーに追加する必要があります。これを行うには、CloneTree メソッドを使用します。作成された要素の親として動作するように、任意の VisualElement をパラメーターとして渡すことができます。

  1. Car_Inspector.cs 内で、スクリプトで VisualTreeAsset のパブリック変数を作成し、それに Car_Inspector_UXML.uxml を割り当てます。

    public VisualTreeAsset m_InspectorXML;
    
  2. CreateInspectorGUI() メソッドを以下のように更新します。

    public override VisualElement CreateInspectorGUI()
    {
         // Create a new VisualElement to be the root of our Inspector UI.
         VisualElement myInspector = new VisualElement();
    
         // Add a simple label.
         myInspector.Add(new Label("This is a custom Inspector"));
    
         // Load the UXML file.
         m_InspectorXML= AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/create-a-custom-inspector/Car_Inspector_UXML.uxml");
    
         // Instantiate the UXML.
         myInspector = m_InspectorXML.Instantiate();
    
         // Return the finished Inspector UI.
         return myInspector;
    }
    
  3. Car コンポーネントがアタッチされているゲームオブジェクトを選択します。car コンポーネントの Inspector に、スクリプトによるものと UI Builder/UXML によるものの 2 つのラベルが表示されます。

    2 つのラベルがあるカスタムインスペクター
    2 つのラベルがあるカスタムインスペクター

テキストフィールドをバインドする

このカスタムインスペクターは、Car クラスのすべてのプロパティを表示します。ユーザーが UI コントロールのいずれかを変更する場合、Car クラスのインスタンス内の値も変更します。そのために、ビジュアルツリーに UI コントロールを追加し、クラスの個々のプロパティにバインドします。

コントロールをシリアル化されたプロパティにバインドするには、コントロールの binding-path フィールドにプロパティを割り当てます。カスタムインスペクターの作成時、バインディングは自動的に行われます。CreateInspectorGUI() は、ビジュアルツリーを返した後に暗示的にバインドします。詳細は、SerializedObject データバインディングを参照してください。

  1. Car_Inspector_UXML.uxml をダブルクリックして、UI Builder で開きます。

  2. TextField コントロールを追加します。

    UI へのテキストフィールドの追加
    UI へのテキストフィールドの追加
  3. TextField の Inspector パネルで、ラベルテキストを Make of the car に設定します。

  4. バインディングパスを m_Make に設定します。

    UI Builder でプロパティをコントロールにバインド
    UI Builder でプロパティをコントロールにバインド
  5. スタイルクラスリストにスタイルクラス unity-base-field__aligned を追加し、テキストフィールドが Inspector ウィンドウの他のフィールドと揃うようにします。詳細については、BaseField を参照してください。

    テキストフィールドにスタイルクラスを追加
    テキストフィールドにスタイルクラスを追加
  6. UI Builder で File > Save を選択します。

  7. Car コンポーネントがアタッチされているゲームオブジェクトを選択します。car コンポーネントの Inspector に Make of the car テキストフィールドが表示されます。テキストフィールドは、Car クラスの m_Make プロパティにバインドされます。

    テキストフィールドを表示するカスタムインスペクター
    テキストフィールドを表示するカスタムインスペクター

プロパティフィールドをバインドする

Car クラスのプロパティを表示するには、各フィールドのコントロールを追加します。また、コントロールはプロパティのタイプと一致する必要があります。例えば、int は Integer フィールドまたは Integer スライダーにバインドする必要があります。

プロパティタイプに基づいて特定のコントロールを追加する代わりに、汎用の PropertyField コントロールを使用することができます。このコントロールは、ほとんどのタイプのシリアル化されたプロパティで動作し、このプロパティタイプのデフォルトインスペクター UI を生成します。

PropertyField の利点は、スクリプト内部で変数の型を変更すると、Inspector の UI が自動的に調整されることです。ただし、UI Builder 内でコントロールのプレビューを取得することはできません。これは、ビジュアルツリーがシリアル化されたオブジェクトにバインドされるまでコントロールの種類がわからないためです。

  1. Car_Inspector_UXML.uxml をダブルクリックして、UI Builder で開きます。

  2. Car クラスの m_YearBuilt プロパティの PropertyField コントロールを追加し、バインディングパスとラベルテキストを設定します。

    UI Builder でのプロパティフィールドの追加
    UI Builder でのプロパティフィールドの追加
  3. スタイルクラス unity-base-field__alignedスタイルクラスリストに追加します。

  4. Car クラスの m_Color プロパティの PropertyField コントロールを追加し、バインディングパスとラベルテキストを設定します。

  5. スタイルクラス unity-base-field__alignedスタイルクラスリストに追加します。

  6. UI Builder で File > Save を選択します。

  7. Car コンポーネントを持つゲームオブジェクトを選択します。これで、car コンポーネントの Inspector に、Year BuiltPaint Color のプロパティフィールドが表示されるようになります。

    カスタムインスペクターとプロパティフィールド
    カスタムインスペクターとプロパティフィールド

カスタムプロパティドローワーの作成

カスタムプロパティドロワーは、カスタムの serializable クラスのためのカスタムインスペクター UI です。その serializable クラスが他のシリアライズされたオブジェクトの一部である場合、カスタム UI は Inspector にそのプロパティを表示します。UI Toolkit では、PropertyField コントロールは、フィールドのカスタムプロパティドロワーが存在する場合、それを表示します。

  1. create-a-custom-inspector フォルダーに、以下のコンテンツで Tire.cs という名前の新しいスクリプトを作成します。

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
        
    [System.Serializable]
    public class Tire
    {
        public float m_AirPressure = 21.5f;
        public int m_ProfileDepth = 4;
    }
        
    
  2. Car.cs 内で Car クラスにリスト Tire を追加します。完成した Car.cs は以下のようになります。

    using UnityEngine;
        
    public class Car : MonoBehaviour
    {
        public string m_Make = "Toyota";
        public int m_YearBuilt = 1980;
        public Color m_Color = Color.black;
        
        // This car has four tires.
        public Tire[] m_Tires = new Tire[4];
    }
    
  3. PropertyField コントロールは、すべての標準的なプロパティタイプで動作し、カスタムのシリアライズ可能なクラスと配列もサポートします。車のタイヤのプロパティを表示するには、別の PropertyFieldCar_Inspector_UXML.uxml に追加して m_Tires にバインドします。完成した Car_Inspector_UXML.uxml は以下のようになります。

    <ui:UXML xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" editor-extension-mode="True">
        <ui:TextField picking-mode="Ignore" label="Make of the car" value="filler text" binding-path="m_Make" class="unity-base-field__aligned" />
        <uie:PropertyField binding-path="m_YearBuilt" label="Year Built" class="unity-base-field__aligned" />
        <uie:PropertyField binding-path="m_Color" label="Paint Color" class="unity-base-field__aligned" />
        <uie:PropertyField label="Tires" binding-path="m_Tires" class="unity-base-field__aligned" />
    </ui:UXML>
        
    
  4. Car コンポーネントを持つゲームオブジェクトを選択します。car コンポーネントの Inspector に Tires プロパティフィールドが表示されます。

    PropertyField コントロールを使用して配列を表示
    PropertyField コントロールを使用して配列を表示

カスタムプロパティドロワー用の UI の作成

カスタムプロパティードロワーを作成し、リスト内の個々の Tire 要素の外観をカスタマイズすることができます。カスタムプロパティドロワーは、Editor 基本クラスから派生する代わりに、PropertyDrawer クラスから派生します。

C# スクリプトまたは UXML を使用して、プロパティの UI を作成できます。この例では、C# スクリプトを使用してカスタム UI を作成します。カスタムプロパティの UI を作成するには、CreatePropertyGUI メソッドをオーバーライドします。

  1. Editor フォルダーに、以下のコンテンツで Tire_PropertyDrawer.cs という名前の新しいスクリプトを作成します。

    using UnityEditor;
    using UnityEditor.UIElements;
    using UnityEngine.UIElements;
        
    [CustomPropertyDrawer(typeof(Tire))]
    public class Tire_PropertyDrawer : PropertyDrawer
    {
        public override VisualElement CreatePropertyGUI(SerializedProperty property)
        {
            // Create drawer UI using C#.
            var popup = new UnityEngine.UIElements.PopupWindow();
            popup.text = "Tire Details";
            popup.Add(new PropertyField(property.FindPropertyRelative("m_AirPressure"), "Air Pressure (psi)"));
            popup.Add(new PropertyField(property.FindPropertyRelative("m_ProfileDepth"), "Profile Depth (mm)"));
        
            // Return the finished UI.
            return popup;
        }
    }
    
  2. Car コンポーネントを持つゲームオブジェクトを選択します。car コンポーネントの Inspector に、Tires プロパティフィールドとカスタムプロパティドロワーが表示されます。

    カスタムプロパティドロワーを使用する Inspector
    カスタムプロパティドロワーを使用する Inspector

デフォルトインスペクターの作成

デフォルトインスペクター UI を表示するフォールドアウトコントロールを作成します。フォールドアウトコントロールにデフォルトインスペクター UI を添付するには、フォールドアウトへの参照を取得する必要があります。フォールドアウトのビジュアル要素は、UQuery を使用して Inspector のビジュアルツリーから取得し、InspectorElement クラスの FillDefaultInspector メソッドを使用することで、デフォルトインスペクター UI をフォールドアウトコントロールに設定できます。

  1. Car_Inspector_UXML.uxml ファイルをダブルクリックして、UI Builder で開きます。

  2. フォールドアウトコントロールを UI に追加し、Default_Inspector という名前を付けて、ラベルテキストを設定します。

    デフォルトインスペクターのフォールドアウト
    デフォルトインスペクターのフォールドアウト
  3. Car_Inspector.cs ファイルで、CreateInspectorGUI() メソッドを更新して Default_Inspector フォールドアウトへのリファレンスを取得し、デフォルトインスペクター UI を設定します。完成した Car_Inspector.cs は以下のようになります。

    using UnityEditor;
    using UnityEditor.UIElements;
    using UnityEngine.UIElements;
        
    [CustomEditor(typeof(Car))]
    public class Car_Inspector : Editor
    {
        public VisualTreeAsset m_InspectorUXML;
        public override VisualElement CreateInspectorGUI()
        {
             // Create a new VisualElement to be the root of our Inspector UI.
            VisualElement myInspector = new VisualElement();
        
            // Add a simple label.
            myInspector.Add(new Label("This is a custom Inspector"));
        
            // Load the UXML file and clone its tree into the inspector.
            if (m_InspectorUXML != null)
            {
                VisualElement uxmlContent = m_InspectorUXML.CloneTree();
                myInspector.Add(uxmlContent);
            }
        
            // Return the finished Inspector UI.
            return myInspector;
        }
    }
        
    
  4. Car コンポーネントを持つゲームオブジェクトを選択します。car コンポーネントの Inspector に、デフォルトインスペクター UI を持つ Default Inspector フォールドアウトが表示されます。

    デフォルトインスペクターを持つ Inspector
    デフォルトインスペクターを持つ Inspector

追加リソース

C# スクリプトを使用したカスタムエディターウィンドウの作成
Create a default Inspector