编辑器拓展:
一、MenuItem:
1.用法:
[MenuItem("Assets/xxxx",false,1)]
2.参数
第一个参数为菜单导航路径,可以在路径最后加上自定义的快捷键。
第二个参数为false表示菜单本身,为true表示作为对应菜单的激活条件,例如:
[MenuItem("Assets/xxxx", false, 1)]
static void appPath()//这个为按钮本身要做的事情
{
Debug.Log("xxxx");
}
[MenuItem("Assets/xxxx", true, 1)]
static bool checkOpen()//这个为判断这个按钮是否激活点击,返回false就无法点击
{
return true;
}
第三个参数为排序数,数值越小越靠前。
二、拓展Project视图
1.右键菜单栏:
MenuItem的路径以Assets开头即可。
2.拓展布局:
选中Project视图中的某一项,为其增添一些元素,监听EditorApplication.projectWindowItemOnGUI委托即可。
例如,在选中的项后面画一个button:
[InitializeOnLoadMethod]
static void Initial()
{
EditorApplication.projectWindowItemOnGUI = delegate (string guid, Rect selectionRect)
{
if (Selection.activeObject && guid == AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(Selection.activeObject)))
//不能用 guid == Selection.assetGUIDs[0]
{
float width = 50f;
selectionRect.x += (selectionRect.width - 50f);
selectionRect.y += 2f;
selectionRect.width = width;
GUI.color = Color.red;
if (GUI.Button(selectionRect, "CLICK"))
{
}
GUI.color = Color.white;
}
};
}
3.监听事件
AssetModificationProcessor类
用于Project视图资源变动相关的事件监听
其中有5个事件可写:
IsOpenForEdit(string,string):当 Unity 检查资源以确定是否应禁用编辑器时,则会调用此方法。
OnWillCreateAsset(string):Unity 在即将创建未导入的资源(例如,.meta 文件)时调用此方法。
OnWillDeleteAsset(string,RemoveAssetOptions):当 Unity 即将从磁盘中删除资源时,则会调用此方法。
OnWillMoveAsset(string,string):Unity 即将在磁盘上移动资源时会调用此方法。
OnWillSaveAssets(string[]):Unity 即将向磁盘写入序列化资源或场景文件时会调用此方法。
使用
public class CustomAssetModificationProcessor : UnityEditor.AssetModificationProcessor
{
static void OnWillCreateAsset(string assetName)
{
Debug.Log("OnWillCreateAsset is being called with the following asset: " + assetName + ".");
}
}
继承自AssetModificationProcessor类,写对应的静态函数即可,注意参数。
三、拓展Hierarchy视图
1.右键菜单栏:
MenuItem的路径以GameObject开头即可。
2.拓展布局:
监听改为EditorApplication.hierarchyWindowItemOnGUI委托即可。
3.重写菜单栏
即在EditorApplication.hierarchyWindowItemOnGUI委托中,判断鼠标右键点击的物体,并修改EditorUtility.DisplayPopupMenu的路径为新的一个路径即可。
代码如下
[InitializeOnLoadMethod]
static void Initial2()
{
EditorApplication.hierarchyWindowItemOnGUI += OnHierarchyGUI;
}
static void OnHierarchyGUI(int instanceID, Rect selectionRect)
{
if (Event.current != null && selectionRect.Contains(Event.current.mousePosition)
&& Event.current.button == 1 && Event.current.type <= EventType.MouseUp)
{
GameObject selectGo = EditorUtility.InstanceIDToObject(instanceID) as GameObject;
if (selectGo)
{
Vector2 mousePos = Event.current.mousePosition;
EditorUtility.DisplayPopupMenu(new Rect(mousePos.x, mousePos.y, 0, 0), "MyNewMenu/Test", null);
Event.current.Use();
}
}
}
[MenuItem("MyNewMenu/Test/hhh", false, 1)]
static void NewMenu()
{
}
注意:一定要定义出自定义路径”MyNewMenu/Test”的子路径,如”MyNewMenu/Test/hhh”,要是没有hhh这一级,Unity会直接崩溃掉。
另外,如果想改原有菜单中已有项的点击逻辑,直接用MenuItem写同样的路径覆盖掉即可。
如:
[MenuItem(“GameObject/UI/Text”, false, 1)]
static void NewMenu()
{
//以后创建Text组件就走这里了。
}
四、拓展Inspector视图
1.拓展源生组件:
让类继承自Editor,打上要修改的组件标签,标签为[CustomEditor(typeof(XXXClass))]
例如:
[CustomEditor(typeof(Camera))]
public class InspectorTest : Editor
{
public override void OnInspectorGUI()
{
if (GUILayout.Button("拓展按钮"))
{
//这里应用GUILayout画,GUILayout由Unity自动计算位置。
}
if (GUI.Button(new Rect(0, 0, 200, 200), "拓展按钮2"))
{
//如果用GUI画,会从Inspector面板左上角算(0,0)点,然后位置被Rect限定住,不适用
}
base.OnInspectorGUI();
}
}
2.拓展继承组件:
通过反射,可以获取一些Editor程序集里的类方法,例如:
[CustomEditor(typeof(Transform))]
public class Script_03_10 :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();
}
}
3.给组件设置不可编辑状态
将组件的某一部分置灰,让它不能被编辑,只需要用GUI.enabled = false;与GUI.enabled = true;夹住要静止的部分即可,例如:
public override void OnInspectorGUI()
{
if (GUILayout.Button("拓展按钮上"))
{
}
//开始禁止
GUI.enabled = false;
base.OnInspectorGUI();
//结束禁止
GUI.enabled = true;
if (GUILayout.Button("拓展按钮下"))
{
}
}
如果想要设置某个物体身上的全部组件不可编辑,只需要设置该物体的hideFlags为HideFlags.NotEditable即可。
HideFlags枚举还可以用于设置对象的某些情况下不保存,以及在某些视图中隐藏。可以用 “|”符号,同时保持多个属性。
4.拓展Context菜单
即在Inspector中右键点击组件弹出来的菜单栏。只需要MenuItem的路径以CONTEXT/XXXComponent(要改的组件)/XXXX 即可,例如:
[MenuItem("CONTEXT/Camera/New Context 1")]
public static void NewContext2(MenuCommand command)
{
Debug.Log(command.context.name);
}
如果要加在Transform组件上,将Camera改为Transform即可,如果所有组件都要加,则改为Component即可。
五、拓展Scene视图
1.画辅助元素(仅仅编辑器模式下做辅助,不会影响游戏最终的发布)
OnDrawGizmosSelected():在选择物体的时候生效。
OnDrawGizmos():即使不选中物体也生效。
例如:
void OnDrawGizmosSelected()
{
Gizmos.color = Color.red;
//画线
Gizmos.DrawLine(transform.position, Vector3.one);
//立方体
Gizmos.DrawCube(Vector3.one, Vector3.one);
}
void OnDrawGizmos()
{
Gizmos.DrawSphere(transform.position, 1);
}
2.拓展对应Object的Scene视图
让类继承自Editor,并且打上标签,和拓展Inspector类似,只是重写的方法改为重写OnSceneGUI。
[CustomEditor(typeof(Camera))]
public class ExampleClass : Editor
{
void OnSceneGUI()
{
Camera camera = target as Camera;
if (camera != null)
{
Handles.color = Color.red;
Handles.Label(camera.transform.position, camera.transform.position.ToString());
Handles.BeginGUI();
GUI.backgroundColor = Color.red;
if (GUILayout.Button("click", GUILayout.Width(200f)))
{
Debug.LogFormat("click = {0}", camera.name);
}
GUILayout.Label("Label");
Handles.EndGUI();
}
}
}
3.上面一种方式只能在选中对应类型的GameObject时绘制元素,如果要在非选中状态下绘制,在SceneView.onSceneGUIDelegate即可。
六、拓展Game视图
给继承自MonoBehaviour的脚本打上[ExecuteInEditMode]标签,可以让它在非运行模式下生效GUI。
例如:
[ExecuteInEditMode]
public class ExampleClass :MonoBehaviour
{
void OnGUI()
{
if (GUILayout.Button("Click"))
{
Debug.Log("click!!!");
}
GUILayout.Label("Hello World!!!");
}
}
七、EditorWindow,自定义窗口:
1.制作自定义窗口,以及常用的生命周期函数:
代码如下:
public class ExampleClass : EditorWindow
{
[MenuItem("Window/Open My Window")]
static void Init()
{
ExampleClass window = (ExampleClass)EditorWindow.GetWindow(typeof(ExampleClass));
window.Show();
}
private Texture m_MyTexture = null;
private float m_MyFloat = 0.5f;
void Awake()
{
Debug.LogFormat("窗口初始化时调用");
m_MyTexture = AssetDatabase.LoadAssetAtPath<Texture>("Assets/unity.png");
}
void OnGUI()
{
GUILayout.Label("Hello World!!", EditorStyles.boldLabel);
m_MyFloat = EditorGUILayout.Slider("Slider", m_MyFloat, -5, 5);
GUI.DrawTexture(new Rect(0, 30, 100, 100), m_MyTexture);
}
void OnDestroy()
{
Debug.LogFormat("窗口销毁时调用");
}
void OnFocus()
{
Debug.LogFormat("窗口拥有焦点时调用");
}
void OnHierarchyChange()
{
Debug.LogFormat("Hierarchy视图发生改变时调用");
}
void OnInspectorUpdate()
{
//Debug.LogFormat ("Inspector每帧更新");
}
void OnLostFocus()
{
Debug.LogFormat("失去焦点");
}
void OnProjectChange()
{
Debug.LogFormat("Project视图发生改变时调用");
}
void OnSelectionChange()
{
Debug.LogFormat("Hierarchy或者Project视图中选择一个对象时调用");
}
void Update()
{
//Debug.LogFormat ("每帧更新");
}
}
2.拓展自定义窗口的下拉菜单:
需要继承接口IHasCustomMenu接口:
void IHasCustomMenu.AddItemsToMenu(GenericMenu menu)
{
menu.AddDisabledItem(new GUIContent("Disable"));
menu.AddItem(new GUIContent("Test1"), true, () => {
Debug.Log("Test1");
});
menu.AddItem(new GUIContent("Test2"), true, () => {
Debug.Log("Test2");
});
menu.AddSeparator("Test/");
menu.AddItem(new GUIContent("Test/Tes3"), true, () => {
Debug.Log("Tes3");
});
}
UnityEditor下的一些常用类:
EditorApplication类:
静态变量
1.EditorApplication.applicationPath
返回Unity编辑器应用程序路径。
示例
[MenuItem("Examples/applicationPath")]
static void appPath()
{
Debug.Log("EditorApplication.applicationPath: " + EditorApplication.applicationPath);
Debug.Log("EditorApplication.applicationContentsPath: " + EditorApplication.applicationContentsPath);
}
输出:
EditorApplication.applicationPath: G:/UnityNew/Unity/Editor/Unity.exe
EditorApplication.applicationContentsPath: G:/UnityNew/Unity/Editor/Data
2.isCompiling、isPaused、isPlaying、isUpdating
编辑器当前是否处于编译脚本、暂停、播放、刷新AssetDatabase
3.projectWindowItemOnGUI、hierarchyWindowItemOnGUI
Project、 Hierarchy 窗口中每个可见列表项的 OnGUI 事件的委托。
委托
1.HierarchyWindowItemCallback、ProjectWindowItemCallback
要在每个 OnGUI 事件上为Hierarchy、Project 窗口中的每个可见列表项调用的委托。
用法:
见Project拓展布局部分。
projectWindowItemOnGUI与hierarchyWindowItemOnGUI两个静态变量分别对应这两个委托。
AssetDatabase类
用于访问资源并针对资源执行操作的接口。
静态函数(大致分类):
1.资源的增、删、复制、查找、移动等:
CreateAsset、CreateFolder、DeleteAsset、CopyAsset、FindAssets、MoveAsset
2.获取相关资源信息等:
GetAllAssetBundleNames、GetAssetBundleDependencies、GetAssetOrScenePath、GetAssetPath、GetDependencies等
3.导入导出:
ImportAsset、ImportPackage、ExportPackage等
4.加载、释放资源:
LoadAllAssetRepresentationsAtPath、LoadAllAssetsAtPath、LoadAssetAtPath、LoadMainAssetAtPath。
RemoveAssetBundleName、RemoveObjectFromAsset、RemoveUnusedAssetBundleNames
5.保存:
SaveAssets。
EditorUtility类:
Editor 实用程序函数。
InstanceIDToObject:将实例 ID 转换为对对象的引用。
DisplayPopupMenu:显示弹出菜单。
Handles类:
场景视图中的自定义 3D GUI 控件和绘制操作。
Handles 类似于 Gizmos,但在交互性和操作方面提供了更多功能。Unity 本身提供的用于在 Scene 视图中操作项目的 3D 控件是 Gizmos 和 Handles 的组合。内置的 Handle GUI 有很多,如通过变换组件定位、缩放和旋转对象等熟悉的工具。不过,您可以自行定义 Handle GUI,以与自定义组件编辑器结合使用。此类 GUI 对于编辑以程序方式生成的场景内容、“不可见”项和相关对象的组(如路径点和位置标记)非常实用。
静态变量:
color:修改颜色。
静态函数:
Handles.BeginGUI:Begin a 2D GUI block inside the 3D handle GUI. 在3D GUI处理中开始一个2D GUI快。
Handles.EndGUI:结束2D GUI编辑,返回3D GUI处理。
Label:在3D空间创建一个文本标签。
以及画各式各样的元素:
DrawLine、Button、DrawCamera等
EditorGUILayout类:
EditorGUI 的自动布局版本。
静态函数:
1.开始、结束类型
BeginScrollView、EndScrollView(开始/结束一个滚动视图)、BeginHorizontal、EndHorizontal、BeginToggleGroup、EndToggleGroup等。
2.输入框、交互框类型:
TextField、IntField、ObjectField、EnumPopup(创建一个枚举弹出选择字段)、Toggle等。
EditorPrefs类:
存储和访问 Unity 编辑器偏好设置。
Unity编辑器为开发者提供了类似PlayerPrefs的数据保存方式EditorPrefs。EditorPrefs是适用于编辑器模式,而PlayerPrefs适用于游戏运行时。
EditorPrefs提供了四种数据的保存:int,float,string,bool。
其静态函数则分为Get、Set、Delete 3类外加一个HasKey。
通过Set方法保存下数据,下次则通过Get方法来获取数据,HasKey方法可以判断是否存在该数据的保存,删除数据调用DeleteKey方法即可。
UnityEngine下的一些常用类:
Event类:
事件与用户输入(按键、鼠标操作)相对应,或者是 UnityGUI 布局或渲染事件。
静态变量
current:返回将被立即处理的当前事件(Event类型)。
变量:
1.鼠标相关:
isMouse:该事件是否是鼠标事件?(只读)
button:已按下哪个鼠标建,0左键,1右键。
clickCount:已收到了多少次连续鼠标点击。
delta:与上次事件相比该鼠标的相对移动。
mousePosition:鼠标位置。
2.键盘相关:
isKey:该事件是否是键盘事件?(只读)
capsLock、control、alt、shift、character等。
3.事件类型:
type:事件类型。枚举为(EventType)
3.公共函数:
1.Use:Event.current.Use() 的含义是不再执行原有操作。
GUI类:
静态变量:
静态函数:
1.创建GUI元素类型:
Button、Box、PasswordField、TextArea(多行文本区域)、TextField(单行文本区域)、Toggle、等
HorizontalScrollbar、VerticalScrollbar(水平/垂直滚动条)
HorizontalSlider、VerticalSlider(水平/垂直滑动条,最大最小值之间更改某值)
BeginScrollView、EndScrollView(开始/结束一个滚动视图)
GUILayout类
静态函数:
Button:创建一个按钮
Gizmos类
辅助图标用于协助在 Scene 视图中进行视觉调试或设置。
所有辅助图标绘图都必须在此脚本的 OnDrawGizmos 或 OnDrawGizmosSelected 函数中进行。每一帧都调用 OnDrawGizmos。在 OnDrawGizmos 中渲染的所有辅助图标均可选择。 仅在选择了附加此脚本的对象时才调用 OnDrawGizmosSelected。
静态变量:
color:为接下来绘制的辅助图标设置颜色。
静态函数:
绘制各种辅助图形元素:
DrawCube:使用 center 和 size 绘制一个实心盒体。
DrawGUITexture、DrawIcon、DrawLine、DrawRay…等
四大GUI系统的大致区别
编辑器中的GUI系统大致分为:
1、UnityEngine.GUI
2、UnityEngine.GUILayout
3、UnityEditor.EditorGUI
4、UnityEditor.EditorGUILayout
GUI系统:
这是运用最广泛的GUI系统,所属命名空间UnityEngine,用其绘制的所有控件不带有自动布局效果,需要手动指定每个控件的绘制位置和大小,自适应性较弱,但开发自由度较高。
GUI系统在编辑器和游戏发布后均可使用。
GUILayout系统:
带自动布局的GUI系统,所属命名空间UnityEngine,用其绘制的所有控件都带有自动布局效果,自适应性较强,但开发自由度较低。
GUILayout系统在编辑器和游戏发布后均可使用。
EditorGUI系统:
适用于编辑器的GUI系统,所属命名空间UnityEditor,用其绘制的所有控件不带有布局效果,需要手动指定每个控件的绘制位置和大小,跟GUI系统的差别是其拥有部分编辑器专用控件,且其只能运行在编辑器内,自适应性较弱,但开发自由度较高。
EditorGUI系统不可以在发布后使用,只能在编辑器中使用。
EditorGUILayout系统:
带自动布局的EditorGUI系统,所属命名空间UnityEditor,用其绘制的所有控件都带有自动布局效果,跟GUILayout系统的差别是其拥有部分编辑器专用控件,且其只能运行在编辑器内,自适应性较强,但开发自由度较低。
EditorGUILayout系统不可以在发布后使用,只能在编辑器中使用。