Unity检视面板的继承方法研究 (二)

  之前做了普通对象的可继承的检视面板类, 现在想要实现对Unity自带的检视面板的继承的话, 要怎样写呢?

  万变不离其宗,  仍然是围绕UnityEditor.Editor.CreateEditor 这个函数来实现:

   /// <summary>
    /// decorate Unity's built-in inspector Editor.
    /// </summary>
    public class DecoratorEditor<T> : UnityEditor.Editor where T : UnityEngine.Object
    {
        protected T _target;
        protected UnityEditor.Editor _nativeEditor;
        private static Type _inspectorEditorType = null;

        public virtual void OnEnable()
        {
            _target = target as T;

            if(_inspectorEditorType == null)
            {
                foreach(Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
                {
                    // get Inspector or Editor
                    var tagType = assembly.GetType("UnityEditor." + typeof(T).Name + "Inspector")
                        ?? assembly.GetType("UnityEditor." + typeof(T).Name + "Editor");
                    if(tagType != null)
                    {
                        _inspectorEditorType = tagType;
                        break;
                    }
                }
            }

            if(_inspectorEditorType != null)
            {
                _nativeEditor = UnityEditor.Editor.CreateEditor(serializedObject.targetObject, _inspectorEditorType);
            }
            else
            {
                _nativeEditor = UnityEditor.Editor.CreateEditor(serializedObject.targetObject);
            }
        }

        public override void OnInspectorGUI()
        {
            if(_nativeEditor)
            {
                _nativeEditor.OnInspectorGUI();
            }
        }

  这里对于内置Unity Inspector的类型查找几乎是在走钢丝, 也只能碰运气了, 好在我只用来修改了一下TextureImporter的检视面板, 因为Unity2019里面没有显示spritePackingTag这个设置了, 可是这个序列化仍然存在.

#if UNITY_2019_1_OR_NEWER
    [CustomEditor(typeof(TextureImporter))]
    public class TextureImporterCustomEditor : DecoratorEditor<TextureImporter>
    {
        public override void OnInspectorGUI()
        {
            if(_target.textureType == TextureImporterType.Sprite)
            {
                _target.spritePackingTag = EditorGUILayout.TextField("Packing Tag", _target.spritePackingTag);
            }
            base.OnInspectorGUI();
        }
    }
#endif

  这样我的设置又回来了.

补充 : 在重写 TextureImporter 的时候, 有一些东西是没有显示出来或是显示错乱的, 比如修改属性后的 Apply, Revert 按钮没有出现, 这就要自己去找它的原始基类里面的方法了...

#if UNITY_2019_1_OR_NEWER
    [CustomEditor(typeof(TextureImporter))]
    [CanEditMultipleObjects]
    public class TextureImporterCustomEditor : DecoratorEditor<TextureImporter>
    {
        private static readonly BindingFlags MethodFlag = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod;

        private bool _changed = false;
        private MethodInfo _apply = null;
        private MethodInfo _resetValues = null;

        #region Mono Funcs
        public override void OnEnable()
        {
            base.OnEnable();

            _apply = _nativeEditor.GetType().GetMethod("Apply", MethodFlag);
            _resetValues = _nativeEditor.GetType().GetMethod("ResetValues", MethodFlag);
        }
        public override void OnInspectorGUI()
        {
            if(_target.textureType == TextureImporterType.Sprite)
            {
                _target.spritePackingTag = EditorGUILayout.TextField("Packing Tag", _target.spritePackingTag);
            }

            base.OnInspectorGUI();

            if(GUI.changed)
            {
                _changed = true;
            }

            if(_changed)
            {
                ChangedButtonGUI();
            }
        }
        private void OnDestroy()
        {
            if(_changed)
            {
                if(CommonEditorUtils.MessageBox("Apply Changes ?"))
                {
                    ApplyChanges();
                }
                else
                {
                    RevertChanges(true);
                }
            }
        }
        #endregion

        #region GUI
        protected void ChangedButtonGUI()
        {
            if(GUILayout.Button("Revert", GUILayout.MaxWidth(50.0f)))
            {
                RevertChanges();
            }
            if(GUILayout.Button("Apply", GUILayout.MaxWidth(50.0f)))
            {
                ApplyChanges();
            }
        }
        #endregion

        #region Main Funcs
        protected void ApplyChanges()
        {
            if(_changed)
            {
                _changed = false;
                EditorUtility.SetDirty(_target);
                if(_apply != null)
                {
                    _apply.Invoke(_nativeEditor, null);
                }
                _target.SaveAndReimport();
            }
        }
        protected void RevertChanges(bool unselectSelf = false)
        {
            if(_changed)
            {
                _changed = false;
                _resetValues.Invoke(_nativeEditor, null);
            }
            if (unselectSelf)
            {
                Selection.activeObject = null;
            }
        }
        #endregion
    }
#endif

省略了一些公共代码, 用反射的方式找到基类方法去实现.

原文地址:https://www.cnblogs.com/tiancaiwrk/p/11418387.html