Unity编辑器拓展最全实现

1编辑器顶部菜单学习

 验证事项

2编辑器Scene菜单学习 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

public class TestSceneMenu : MonoBehaviour
{  

    [InitializeOnLoadMethod]   //加入这个属性,就相当于在编辑器启动的时候执行
    static void Ind() {
        UnityEditor.SceneView.duringSceneGui += (u) =>
        {
            //在Scene窗口绘制菜单,只需要在DuringSceneGui绑入一个事件即可

            if (Event.current != null &&Event.current.button == 1 && Event.current.type == EventType.MouseUp){
                //if里面是描述鼠标右键事件按下,

                Rect position = new Rect(Event.current.mousePosition.x, Event.current.mousePosition.y-100,100,100);
                //描绘菜单的Rect方框的位置

                GUIContent[] contens = new GUIContent[] { new GUIContent("Test1"),new GUIContent("先锋/Test2")};
                //菜单里面的按钮数组
                EditorUtility.DisplayCustomMenu(position, contens,-1,(data, opt, select)=> {
                    Debug.LogFormat("data:{0},opt:{1},select:{2},value:{3}",data,opt,select,opt[select]);
                },null);

                //这是描绘菜单按钮所需要传入的属性,(位置,按钮数组,是否选择(传入按钮数组没有的下标代表不选择),每个按钮所需要处理的点击回调,一般传入空值即可)

                Event.current.Use();   //将鼠标复原到指针icon
            }
        };
    }
    
}

3编辑器如何给按钮添加快捷键学习

4Assets菜单栏拓展

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

public class TestProject : MonoBehaviour
{



    [MenuItem("Assets/Test1")]
    static void Test1()
    {
        Debug.Log("Assets  Test1");
        //Project文件夹下的按钮,直接把路径改成Assects即可
    }


    /// <summary>
    /// 在资源右侧加上按钮
    /// </summary>
    [InitializeOnLoadMethod]
    static void InitializeOnLoad()
    {

        //这个是在Project的窗口创建按钮   guid是Assects下所有资源的唯一标识符   
        //rect每个资源所占的选中方框大小,
        EditorApplication.projectWindowItemOnGUI += (guid, rect) =>
        {

            //是否选中资源
            if (Selection.activeObject != null)
            {

                //获取资源的GUID唯一标识符
                string Select_guid = AssetDatabase.AssetPathToGUID(AssetDatabase.GetAssetPath(Selection.activeObject));
                //判断传入的唯一标识符和点击的唯一标识符是否一致
                if (guid == Select_guid&&!string.IsNullOrEmpty (Select_guid))
                {
                    //按照所占方框去创建按钮大小
                    rect.x = rect.width - 100;
                    rect.width = 100;
                    if (GUI.Button(rect, "delect"))
                    {
                        //删除资源方法
                        AssetDatabase.DeleteAsset(AssetDatabase.GetAssetPath(Selection.activeObject));
                        Debug.LogFormat("资源唯一标识符:{0}", Select_guid);
                    }

                }

            }

        };
    }
}

 5Project事件介绍

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

public class TestProjectEvent : UnityEditor.AssetModificationProcessor
{
    /// <summary>
    /// 将要创建资源的会执行的方法
    /// </summary>
    /// <param name="Path"></param>
    public static void OnWillCreateAsset(string Path)
    {
        Debug.LogFormat("创建资源{0}", Path);
    }

    /// <summary>
    /// 点击Apply保存资源所执行的方法
    /// </summary>
    /// <param name="paths"></param>
    /// <returns></returns>
    public static string[] OnWillSaveAssets(string[] paths)
    {

        for (int i = 0; i < paths.Length; i++)
        {
            Debug.LogFormat("保存的资源{0}", paths[i]);
        }
        return paths;
    }


    /// <summary>
    /// 移动资源所执行的方法
    /// </summary>
    /// <param name="OldPath"></param>
    /// <param name="NewPath"></param>
    /// <returns></returns>
    public static AssetMoveResult OnWillMoveAsset(string OldPath, string NewPath)
    {

        Debug.LogFormat("移动资源从{0}到{1}", OldPath, NewPath);
        ///需要返回枚举
        return AssetMoveResult.DidNotMove;   //允许移动
        //return AssetMoveResult.DidMove;    //不允许移动
        //return AssetMoveResult.FailedMove;   //不允许移动

    }


    /// <summary>
    /// 删除资源所执行的方法    删除资源的路径,操作的枚举,枚举中表述的是删除之后是否进入回收站
    /// </summary>
    /// <param name="path"></param>
    /// <param name="opt"></param>
    /// <returns></returns>
    public static AssetDeleteResult OnWillDeleteAsset(string path, RemoveAssetOptions opt)
    {


        Debug.LogFormat("删除资源:{0}  options:{1}", path, opt);



        return AssetDeleteResult.DidNotDelete;  //可以删除
        //return AssetDeleteResult.DidDelete;   //不能删除
        //return AssetDeleteResult.FailedDelete;   //不能删除
    }


    /// <summary>
    /// 这个标头是项目初始化,监听资源发生变化
    /// </summary>
    [InitializeOnLoadMethod]
    static void InitOnLoad()
    {

        ///根据不同回调监听不同界面的资源回调
        EditorApplication.projectChanged += () =>
        {
            Debug.Log("资源发生改变");
        };

        EditorApplication.hierarchyChanged+=()=> {
            Debug.Log("层级资源发生改变");
        };
    }


}

6层级面板的拓展

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

public class TestHierarchy : MonoBehaviour
{

    /// <summary>
    /// 层级面板右键按钮拓展
    /// </summary>
    [MenuItem("GameObject/Test2", false, 0)]
    public static void Test2()
    {
        Debug.Log("GameObject  Test2");
        
    }

    /// <summary>
    /// 在层级资源右侧加上按钮
    /// </summary>
    [InitializeOnLoadMethod]
    static void InitializeOnLoad()
    {

        //这个是在Hierarchy的资源左侧创建按钮   InstancesID是Hierarchy下所有资源的唯一ID  
        //rect每个资源所占的选中方框大小,
        EditorApplication.hierarchyWindowItemOnGUI += (InstancesID, rect) =>
        {
            //是否选中资源   判断选择的资源id和传入的ID是否相等
            if (Selection.activeObject != null&&InstancesID==Selection.activeObject.GetInstanceID())
            {                               
                    //按照所占方框去创建按钮大小
                    rect.x = rect.width - 50;
                    rect.width = 100;
                    if (GUI.Button(rect, "delect"))
                    {
                    //删除资源方法
                    GameObject.DestroyImmediate(Selection.activeObject);
                        Debug.LogFormat("删除资源:{0}", InstancesID);
                    }              
            }

        };
    }


}

7抛弃原来的菜单,重新创建菜单

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

public class TestMenuOverride
{

    [InitializeOnLoadMethod]
    static void InitOnLoad() {
        ///监听鼠标在层级面板窗口
        EditorApplication.hierarchyWindowItemOnGUI += (InstanceID, rect) =>
        {
            if (Event.current != null)
            {
                ///判断右键抬起
                if (Event.current.button == 1 && Event.current.type == EventType.MouseUp)
                {
                    //阻断本身的右键菜单展出
                    //Event.current.Use();

                    //创建自己的菜单按钮,可以看到本身自己的菜单,在”先锋“的地方传入自己的菜单名称即可
                    //EditorUtility.DisplayPopupMenu(new Rect(Event.current.mousePosition.x, Event.current.mousePosition.y, 100, 100)
                      //  ,"先锋",null);

                    Debug.Log("鼠标抬起");                    
                }
            }

        };
    }

}

8在Inspector面板组件拓展 (在代码或者组件下面加按钮)

using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

/// <summary>
/// CustomEditor属性指定类型,下面就是在Camera组件加入按钮
/// </summary>
[CustomEditor(typeof(Camera))]
public class TestInspector : Editor
{

    public override void OnInspectorGUI()
    {
        base.OnInspectorGUI();  //保持原生的组件属性  

        ///加入按钮,并且监听按钮按下
        if (GUILayout.Button("Test1")){
            Debug.Log("雨一直下,气氛不算融化ikun");

            ///获取目标组件
            Camera c = this.target as Camera;
            if (c != null) {
                c.fieldOfView = 10;
            }
        }

    }

}

9在Inspector Context组件拓展(组件右键面板加按钮)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

public class TestInspectorContext : MonoBehaviour
{

    /// <summary>
    /// 命名规则   CONTEXT/组件名字(代码名字)/按钮名字)
    /// </summary>
    /// <param name="command"></param>
    [MenuItem("CONTEXT/Transform/Test1")]
    static void SetPosition(MenuCommand command) {

        Transform transform = command.context as Transform;

        if (transform != null) {
            transform.position = Vector3.zero;
            Debug.Log("重置位置");
        }
    }
    


}

10Scene视图拓展(Gizmos画图)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestScene : MonoBehaviour
{

#if UNITY_EDITOR

    public  Color color;

    /// <summary>
    /// 选中才绘制
    /// </summary>
    private void OnDrawGizmosSelected()
    {
        Gizmos.DrawLine(transform .position,transform .position +Vector3 .up);
        Gizmos.color = color;
        Gizmos.DrawSphere(transform.position ,1);
    }

    /// <summary>
    /// 一直绘制
    /// </summary>
    private void OnDrawGizmos()
    {
        //Gizmos.DrawLine(transform.position, transform.position + Vector3.up);
        //Gizmos.color = color;
        //Gizmos.DrawSphere(transform.position, 1);


    }
#endif

}

11在Scene视图加UI

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

[CustomEditor(typeof(TestScene))]
public class TestSceneGUI : Editor
{
    private void OnSceneGUI()
    {
        Handles.BeginGUI();    //3d中开始2D块
        if (GUILayout.Button("TestScene",GUILayout.Width (100))) {
            Debug.Log("This TestScene");
        }

        Handles.EndGUI();
    }
}

12在Scene视图加固定的UI

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

[CustomEditor(typeof(TestScene))]
public class TestSceneGUI : Editor
{
    private void OnSceneGUI()
    {
        Handles.BeginGUI();    //3d中开始2D块
        if (GUILayout.Button("TestScene",GUILayout.Width (100))) {
            Debug.Log("This TestScene");
        }

        Handles.EndGUI();
    }



    [InitializeOnLoadMethod]
    static void InitLoad() {
        //代码启动就开始画UI
        SceneView.duringSceneGui += (sceneView) =>
        {
            Handles.BeginGUI();    //3d中开始2D块
            //按钮
            if (GUILayout.Button("Test2", GUILayout.Width(100)))
            {
                Debug.Log("This TestScene");
            }
            //标签
            GUILayout.Label("先锋");

            Handles.EndGUI();
        };
    }
}

13Game视图增加拓展

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 这个特性运行在编辑器下,不需要运行就能出现按钮,如果
/// 不加属性,需要运行才会出现在Game视图(需要将代码挂载到物体上)
/// </summary>
[ExecuteInEditMode]
public class TestGame : MonoBehaviour
{
    private void OnGUI()
    {
        if (GUILayout.Button("Test1",GUILayout.Width(100))) {
            Debug.Log("Test Scene");
        }
    }
}

14在编辑器下创建自己的窗口

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

public class TestWindow : EditorWindow
{
    /// <summary>
    /// 在窗口中创建一个按钮
    /// </summary>
    private void OnGUI()
    {
        if (GUILayout.Button("创建对象")) {
            Debug.Log("创建模型");
        }
    }


    //以下都是生命周期

    /// <summary>
    /// 窗口启动
    /// </summary>
    private void Awake()
    {
        Debug.Log("Awake");
    }

    /// <summary>
    /// 窗口销毁
    /// </summary>
    private void OnDestroy()
    {
        Debug.Log("OnDestroy");
    }

    /// <summary>
    /// 鼠标焦点,当鼠标出去再进来会执行一次
    /// </summary>
    private void OnFocus()
    {
        Debug.Log("OnFocus");
    }


    /// <summary>
    /// 窗口常输出
    /// </summary>
    private void Update()
    {
        Debug.Log("Update");
    }
}

创建一个按钮打开窗口

15窗口中右上角下拉菜单的拓展

效果图

 

 16 在自己创建的Window窗口创建模型预览窗口

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

public class TestPreview : EditorWindow
{

    Object Obj;   //
    Editor PreviewObj;

    Object LatsObj;

    /// <summary>
    /// 创建一个文件输入窗口
    /// </summary>
    private void OnGUI()
    {
        //可以在这里点击输出框
        Obj=EditorGUILayout.ObjectField(Obj,typeof(Object),false);

        //创建一个窗口
        if (Obj!=null&&Obj!= LatsObj) {
            PreviewObj = Editor.CreateEditor(Obj);
            LatsObj = Obj;
        }

        //创建预览画面
        if (PreviewObj != null) {
            PreviewObj.OnPreviewGUI(GUILayoutUtility.GetRect(400, 400), EditorStyles.label);
        }
        

    }


    /// <summary>
    /// 打开预览窗口
    /// </summary>
    [MenuItem("先锋/预览窗口")]
    static void Test3() {
        TestPreview tp = EditorWindow.GetWindow<TestPreview>();
        tp.Show();
    }

}

 效果实现

猜你喜欢

转载自blog.csdn.net/qq_37335907/article/details/128013656