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
复制代码

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

posted @   tiancaiKG  阅读(583)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示