LoginSignup
3

More than 1 year has passed since last update.

【Unity】デフォルトのカスタムエディタを実装可能なisFallbackフラグの紹介【CustomEditor】

Last updated at Posted at 2022-10-07

はじめに

UI Toolkit(UIElements)でUI作ってたら CustomEditor 属性に便利なフラグを見つけたので紹介します。

環境

  • Unity2021.3.0f1

背景と問題点

背景

「IMGUIはもう嫌だ!俺はUI ToolkitでUIを作るんだ!」となってカスタム PropertyDrawer を書いたとします。

試しに以下のようなコンポーネントと、UI Toolkit(というか VisualElement)を使って描画する PropertyDrawer を実装してみます。

SampleComponent.cs
using System;
using UnityEngine;

public class SampleComponent : MonoBehaviour
{
    public SampleClassWithIMGUI sampleClassWithIMGUI;
    public SampleClassWithUIToolkit sampleClassWithUIToolkit;
}

[Serializable]
public class SampleClassWithIMGUI
{
    public bool isUIToolkit = false;
}

[Serializable]
public class SampleClassWithUIToolkit
{
    public bool isUIToolkit = true;
}
SampleClassWithUIToolkitPropertyDrawer.cs
#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;

[CustomPropertyDrawer(typeof(SampleClassWithUIToolkit))]
public class SampleClassWithUIToolkitPropertyDrawer : PropertyDrawer
{
    public override VisualElement CreatePropertyGUI(SerializedProperty property)
    {
        return new PropertyField(property)
        {
            // 色を赤くしてみる
            style = { color = new StyleColor(Color.red) },
        };
    }
}
#endif

上記の SampleComponent を適当な GameObject につけると、Inspectorはこうなります。

SampleScene_-UI_Toolkit_Test-Windows__Mac__Linux-Unity_2021_3_0f1__Metal.png

IMGUIで描画されるクラス SampleClassWithIMGUI は通常通り描画されてますが、UI Toolkitで描画したい SampleClassWithUIToolkit クラスは謎の "No GUI Implemented" というメッセージが出るだけで描画されてません。

これはフォーラムの投稿によると

That is, you need to make sure to override CreateInspectorGUI() on the Editor class for your object and then populate manually with PropertyFields. This is a temporary situation until we switch the default inspectors of all objects to UIElements (right now default inspectors still use IMGUI).

つまり、オブジェクトのEditorクラスでCreateInspectorGUI()をオーバーライドし、PropertyFieldsを手動で入力する必要があります。これは、すべてのオブジェクトのデフォルトインスペクタをUIElementsに切り替えるまでの一時的な状況です(現在、デフォルトインスペクタはまだIMGUIを使用しています)。

(DeepL翻訳)

だからだそうで、 SampleComponent のカスタム Editor を実装すればOKです。

SampleComponentEditor.cs
// 参考:
// https://issuetracker.unity3d.com/issues/propertydrawer-dot-createpropertygui-will-not-get-called-when-using-a-custompropertydrawer-with-a-generic-struct

#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine.UIElements;

[CustomEditor(typeof(SampleComponent))]
public class SampleComponentEditor : Editor
{
    public override VisualElement CreateInspectorGUI()
    {
        var container = new VisualElement();

        // IMGUI同様のInspectorを実装
        InspectorElement.FillDefaultInspector(container, serializedObject, this);

        return container;
    }
}
#endif

SampleScene_-UI_Toolkit_Test-Windows__Mac__Linux-Unity_2021_3_0f1__Metal.png

これでUI Toolkitでも描画されるようになりました。めでたしめでたし。

問題点

すでにお気づきかと思われますが、これだと

「UI Toolkitでカスタムプロパティドロワーを実装したら、その対象クラスを使用するクラスは必ずカスタムエディタを書かないといけない」

ということになってしまいます(正気か!?)。

この問題の解決方法として、先に上げた SampleComponentEditor のような汎用クラスを作って「これを継承すればカスタム Editor を数行で実装できる」というのを見たのですが、もっとスマートな方法があったので紹介します。

CustomEditorisFallback フラグ

解決方法は以下のカスタム Editor を一つ追加するだけです。

SampleComponentEditor みたいな個別のカスタム Editor は必要ありません。

DefaultEditor.cs
// 参考URL:
// https://forum.unity.com/threads/property-drawers.595369/#post-5118800

#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;

[CustomEditor(typeof(Object), true, isFallback = true)]
public class DefaultEditor : Editor
{
    public override VisualElement CreateInspectorGUI()
    {
        var container = new VisualElement();

        // IMGUI同様のInspectorを実装
        InspectorElement.FillDefaultInspector(container, serializedObject, this);

        return container;
    }
}
#endif

CustomEditorisFallback というフラグを true にすると

  「他に適用されるカスタム Editor が存在しない場合のデフォルト Editor

として使用されます。

以下は ドキュメント からの引用です。

CustomEditor.isFallback

public bool isFallback;

Description
If true, match this editor only if all non-fallback editors do not match. Defaults to false.

Unity does a two-pass match to hook up editors with inspected types. First the non-fallback editors are tested, and if none match, then the fallbacks are tested for a match. Setting this flag lets you set up a default editor for a given type, while still permitting another editor type to override it.

trueの場合、フォールバックしないエディタがすべてマッチしない場合にのみ、このエディタをマッチさせます。デフォルトはfalseです。

Unityは、検査されたタイプのエディタをフックするために、2パスマッチを行います。まず、フォールバックでないエディタがテストされ、マッチするものがなければ、フォールバックがマッチするかどうかテストされます。このフラグを設定することで、特定のタイプのデフォルトエディタを設定することができ、同時に他のエディタタイプによるオーバーライドを許可することができます。

(DeepL翻訳)

これググっても日本語の情報が出てこないのですが、ドキュメントをさかのぼっていくと少なくともUnity2017.1の時点で存在してたみたいです。

isFallback フラグが true のものが複数ある場合はどうなるのか気になりますが、未検証です。知ってる人いたら教えて下さい。

最後に

というわけでUI Toolkit使用時の注意点と CustomEditorisFallback フラグの紹介でした。

ちなみに今回起きた問題はUnity2022.1で対応済みなので、最新のUnityを使用している場合は気にする必要がありません。 Unity2022.1.0f1(Apple Silicon版)で検証しましたが直ってませんでした。

あと実は紹介した DefaultEditor の実装にも問題があり、一番上に描画されるスクリプトの PropertyField をクリックしてもスクリプトファイルがpingされない問題があるのですが、それについてはまた別の記事で書こうと思います書きました。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3