目录
1、拓展源生组件
2、拓展继承组件
3、组件不可编辑
4、Context菜单
1、拓展源生组件
摄像机就是典型的源生组件。它的局限性就是拓展组件只能加在源生组件的最上面或者最下面,不能插在中间,不过这样也就够了
using UnityEngine;
using UnityEditor;
[CustomEditor(typeof(Camera))]
public class S3_拓展源生组件 : Editor
{
public override void OnInspectorGUI()
{
if (GUILayout.Button("拓展按钮"))
{}
base.OnInspectorGUI();
}
}
CustomEditor()表示自定义哪个组件,OnInspectorGUI()可以对它进行重新绘制,base.OnInspectorGUI()表示是否绘制父类原有元素。
2、拓展继承组件
Unity大量的Editor绘制方法封装在内部DLL文件里,开发者无法调用它的方法。可以使用C#反射的方式调用内部未公开的方法。通过拓展Transform组件,现在就可以保留原有的绘制方式
通过反射先得到UnityEditor.TransformInspector对象,然后就可以调用它内部的OnInspectorGUI()方法
using UnityEngine;
using UnityEditor;
using System.Reflection;
[CustomEditor(typeof(Transform))]
public class S3_拓展继承组件 : Editor
{
private Editor m_Editor;
void OnEnable()
{
m_Editor = Editor.CreateEditor(target, Assembly.GetAssembly(typeof(Editor)).GetType("UnityEditor.TransformInspector", true));
}
public override void OnInspectorGUI()
{
if (GUILayout.Button("拓展按钮"))
{
}
m_Editor.OnInspectorGUI();
//base.OnInspectorGUI();
}
}
上面重写了OnInspectorGUI()方法。使用GUILayout.Button绘制了自定义的按钮元素,接着调用m_Editor.OnInspectorGUI()绘制Transform原有面板信息,这样我们拓展的按钮就会显示在Transform面板上方
现在每个Transform组件下都有一个拓展按钮
3、组件不可编辑
将Transform组件的原始功能禁掉(灰色表示不可编辑),而不影响我们上下拓展的两个按钮
using UnityEngine;
using UnityEditor;
using System.Reflection;
[CustomEditor(typeof(Transform))]
public class S3_组件不可编辑 : Editor
{
private Editor m_Editor;
void OnEnable()
{
m_Editor = Editor.CreateEditor(target, Assembly.GetAssembly(typeof(Editor)).GetType("UnityEditor.TransformInspector", true));
}
public override void OnInspectorGUI()
{
if (GUILayout.Button("拓展按钮上"))
{
}
//开始禁止
GUI.enabled = false;
m_Editor.OnInspectorGUI();
//结束禁止
GUI.enabled = true;
if (GUILayout.Button("拓展按钮下"))
{
}
}
}
禁用整个组件
从右键菜单中选择3D Object->Lock->Lock(锁定)或者Unlock(解锁)
原理就是设置游戏对象的hideFlags。也可以不设置游戏对象的hideFlags,也可以单独给某个组件设置hideFlags,这样只会影响到一个组件并非全部。
[MenuItem("GameObject/3D Object/Lock/Lock",false,0)]
static void Lock()
{
if(Selection.gameObjects != null)
{
foreach(var gameObject in Selection.gameObjects)
{
gameObject.hideFlags = HideFlags.NotEditable;
}
}
}
[MenuItem("GameObject/3D Object/Lock/UnLock" , false , 1)]
static void UnLock()
{
if(Selection.gameObjects != null )
{
foreach(var gameObject in Selection.gameObjects)
{
gameObject.hideFlags = HideFlags.None;
}
}
}
-
HideFlags.None:清除状态
-
HideFlags.DontSave:设置对象不会被保存(仅编辑模式下使用,运行时剔除掉)
-
HideFlags.DontSaveInBuild:设置对象构建后不会被保存
-
HideFlags.DontSaveInEditor:设置对象编辑模式下不会被保存
-
HideFlags.DontUnloadUnusedAsset:设置对象不会被Resources.UnloadUnused-Assets()卸载无用资源时卸掉
-
HideFlags.HideAndDontSave:设置对象隐藏,并且不会被保存
-
HideFlags.HideInHierarchy:设置对象在层次视图中隐藏
-
HideFlags.HideInInspector:设置对象在控制面板视图中隐藏
-
HideFlags.NotEditable:设置对象不可被编辑
4、Context菜单
using UnityEngine;
using UnityEditor;
public class S3_4Context菜单
{
[MenuItem("CONTEXT/Transform/New Context 1")]
public static void NewContext1(MenuCommand command)
{
Debug.Log(command.context.name);
}
[MenuItem("CONTEXT/Transform/New Context 2")]
public static void NewContext2(MenuCommand command)
{
Debug.Log(command.context.name);
}
}
[MenuItem("CONTEXT/Transform/New Context 1")]表示将新菜单扩展在Transform组件上。如果想给所有组件都添加菜单栏,这里改成Component即可
以上设置也可以应用在自己的脚本中,在代码中可以通过MenuCommand来获取脚本对象,从而访问脚本中的变量。
#if UNITY_EDITOR //表示这段代码会在Editor模式下进行,发布后将被剔除掉
using UnityEditor;
#endif
using UnityEngine;
public class tests : MonoBehaviour
{
public string contextName;
#if UNITY_EDITOR
[MenuItem("CONTEXT/tests/New Context 1")]
public static void NewContext2(MenuCommand command)
{
tests script = (command.context as tests);
script.contextName = "hello world";
}
#endif
}
[ContextMenu("Remove Component")]
void RemoveComponent() //重写删除组件的按钮
{
Debug.Log("RemoveComponent");
//等一帧后再删除自己
UnityEditor.EditorApplication.delayCall = delegate ()
{
DestroyImmediate(this);
};
}
编辑情况下的代码可能会出现问题。比如DestroyImme(this)删除自己的代码时,会触发引擎底层的一个错误,不过可以用UnityEditor.EditorApplication.delayCall来延迟一帧调用