Help us understand the problem. What is going on with this article?

手抜きしてインスペクター拡張

More than 5 years have passed since last update.

Unityで手抜きしてインスペクターを拡張する方法

手抜きその1 「エディタ拡張せずに、インスペクターから更新」

サンプルとしてUnity4.3で使用可能になったSpriteの表示サイズを変更するコンポーネントを作ってみましょう。
「インスペクター上で入力されたサイズの値によって、Transformのスケール値を変更する」というクラスです。

ScreenClip [2].png

CustomSprite.cs
using UnityEngine;
[ExecuteInEditMode]
[AddComponentMenu("2D/CustomSprite")]
[RequireComponent (typeof (SpriteRenderer))]
public class CustomSprite : MonoBehaviour
{
    //表示スプライトのサイズ
    [SerializeField]
    Vector2 customSize = Vector2.zero;
    public Vector2 Size { 
        get { return customSize; }
        set { customSize = value; RefreshSize(); }
    }

    //スプライトの基本のサイズ
    Vector2 baseSize = Vector2.zero;
    public Vector2 BaseSize { get { return baseSize; } }

    void Awake()
    {
        RefreshSize();
    }

    void Update()
    {
        //毎フレーム更新?重い処理には使えない
        //RefreshSize()
    }

    //インスペクターの値が変更されるたびに呼ばれる
    void OnValidate()
    {
        RefreshSize();
    }

    //インスペクターの値に合わせて表示する大きさを変える
    void RefreshSize()
    {
        Sprite sprite = this.GetComponent<SpriteRenderer>().sprite;
        if (null != sprite)
        {
            baseSize = new Vector2(sprite.rect.width, sprite.rect.height);
            this.transform.localScale = new Vector3(customSize.x / BaseSize.x, customSize.y / BaseSize.y, 1);
        }
    }
}

ポイントは、OnValidate()です。
これは、インスペクターの値が変化した際に呼ばれるコールバックです。
「インスペクターの見た目は変えなくていいけど、値の変化はリアルタイムに反映させたい」
という場合は、エディター拡張せずにこれを使えばOKです。
Unity4.2以降での追加機能になるため、機能の強力さのわりには意外に知られてないかと思います。

手抜きその2 「カスタムインスペクターをなるべく簡単に書く」

さて、スプライトのサイズを変更できるようにはなりましたが、
使ってみると「元のサイズに戻す」ボタンが欲しくなってきました。
となると、エディター拡張でカスタムインスペクターのクラスを書くしかないですが、
「元の表示はほぼそのままでボタンを追加するだけ」なので、できるなら簡単に書きたいものです。
ついでに、表示するラベル名もCustomSize ではなくSizeにしてみましょう。

ScreenClip [3].png

CustomSpriteInspector.cs
using UnityEngine;
using UnityEditor;

[CanEditMultipleObjects]
[CustomEditor(typeof(CustomSprite))]
public class CustomSpriteInspector : Editor
{
    public override void OnInspectorGUI()
    {
        serializedObject.Update();
        DrawProperties();
        serializedObject.ApplyModifiedProperties();
    }

    //各要素の描画
    void DrawProperties()
    {
        CustomSprite obj = target as CustomSprite;
        EditorGUILayout.BeginHorizontal();

        //PropertyFieldを使えば、型に合わせて基本通り描画してくれる。
        //面倒なUndo処理とかも書かなくてもいい、
        EditorGUILayout.PropertyField(serializedObject.FindProperty("customSize"), new GUIContent("Size"));

        //リセットボタン
        if (GUILayout.Button("Reset", GUILayout.Width(50f)))
        {
            //こういう独自処理はUndo書く必要がある
            Undo.RecordObject(obj, "CustomSize Reset");
            obj.Size = obj.BaseSize;
            EditorUtility.SetDirty(target);
        }

        EditorGUILayout.EndHorizontal();
    }
}

ポイントは、EditorGUILayout.PropertyField()です。
これを使えば、IntFieldだの、Vector2Fieldだの、ColorFieldだのと使い分ける必要がなくなります。
元の型に合わせて表示されるので、とっても楽。
おまけにUndo処理もやってくれます。
サンプルでは一つだけしかパラメーターがないですが、何個もパラメーターがあるのが普通なので、そういった場合は特に効果を実感できると思います。
ただし、serializedObject.FindPropertyではメンバ変数を文字列で検索するため、元のメンバ変数をリネームするときだけは注意してください。
(Unityではリネームはそうそうしないと思いますが)

実際にエディタ拡張していると
基本はデフォルト表示のままでOKだけど、
「一部だけ変えたい」
「レイアウトを変えたり表示ラベル名を変えたい」
「ちょっとしたショートカット機能のボタンだけつけたい」

ということが殆どだと思います。
そんな場合は、このEditorGUILayout.PropertyField()を使えば、とても楽になります。
上記のOnValidateと合わせて使えば、もろもろの更新も自動でかけることができるため、かなりスッキリとコードが書けます。

注)

ただし、唯一の弱点が。
OnValidateで読んだ際には、子オブジェクトなどGameObjectの作成を自動で作成することができないようです。
参考 http://anchan828.hatenablog.jp/entry/2013/11/18/012021
こういった場合は、OnValidate内ではisChanedなどのフラグだけ立てておいて、Updateで監視して更新をかけるという手法でもいいかもしれません。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした