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
省略了一些公共代码, 用反射的方式找到基类方法去实现.