うにてぃブログ

UnityやUnreal Engineの記事を書いていきます

【Unity】Unity デフォルト型の Inspector 拡張

UnityのInspector拡張を行う際にはCustomEditorを利用するが
Unityのデフォルト型 (Transform や RectTransform等) の機能を残しつつ拡張する場合は
同じ処理を書く必要が出てくるそのため、以下のようなabstractを作成するといくらか拡張がマシになる

using UnityEditorInternal;
using UnityEngine;
 
namespace UnityEditor
{
    public abstract class InternalEditorExtensionAbstract<T> : Editor where T : Component
    {
        private Editor _editor;
        protected T targetComponent;
  
        protected abstract string GetTypeName();
        
        private void OnEnable()
        {
            var type = typeof(EditorApplication).Assembly.GetType(GetTypeName());
            targetComponent = target as T;
            _editor = CreateEditor(targetComponent, type);
            Enable();
        }
  
        private void OnDisable()
        {
            DestroyImmediate(_editor);
            Disable();
        }
        
        public sealed override void OnInspectorGUI()
        {
            _editor.OnInspectorGUI();
        }
    }
}

例えば Transform の拡張をしたい場合は下記のように記述することでグローバルパラメータを見ることができる

using UnityEngine;
 
namespace UnityEditor
{
    [CustomEditor(typeof(Transform))]
    public class InspectorExtensionTransform : InternalEditorExtensionAbstract<Transform>
    {
        protected override string GetTypeName()
        {
            return "UnityEditor.TransformInspector";
        }
 
        protected override void InspectorGUI()
        {
            using (new EditorGUI.DisabledScope(true))
            {
                EditorGUILayout.LabelField("World (Read Only)");
                EditorGUILayout.Vector3Field("Position", targetComponent.position);
                EditorGUILayout.Vector3Field("Rotation", targetComponent.rotation.eulerAngles);
                EditorGUILayout.Vector3Field("Scale", targetComponent.lossyScale);
            }
        }
    }
}

問題点

CanEditMultipleObjects

CanEditMultipleObjects を利用した際にInspectorの表示が - にならず複数の値を操作することができない
そのため

using (var check = new EditorGUI.ChangeCheckScope())
{
    _editor.OnInspectorGUI();
    if (check.changed && targets.Length > 1)
    {
        ComponentUtility.CopyComponent(targetComponent);
        foreach (var o in targets)
            ComponentUtility.PasteComponentValues(o as T);
    }
}

のような処理を入れると適応されるが、すべてのパラメータを更新してしまうため意図しない挙動になってしまう

そして、もとと同じような実装をしようとしても、internalクラスが利用されているため、結局できないことが多い

特定のコンポーネントを上書きができない

私の知る範囲だとUnityEngine.UI.Imageのみであるが CustomEditor(typeof(Image)) をしても上書きできない
調べても理由は分からなかった

また、 UnityEngine.SpriteRenderer の Color プロパティも CustomPropery(typeof(Color)) で上書くことができない
内部を見たところPropertyFieldを使っているため、できそうな気がするが無理だった