跟着书学Unity-《Unity3D游戏开发》宣雨松编著-(一)Unity的基础知识、编辑器结构、及拓展编辑器(拓展Project视图)_unity3d游戏开发宣雨松第三版 pdf-CSDN博客

跟着书学Unity-《Unity3D游戏开发》宣雨松编著-(二)拓展编辑器(拓展Hierarchy视图、拓展Inspector视图)_《unity 3d游戏开发(第2版)》(宣雨松) pdf-CSDN博客

目录

3拓展编辑器

3.4拓展Sence视图

3.4.1辅助元素

3.4.2辅助UI

3.4.3辅助常驻UI

3.4.4禁用选中对象

3.5拓展Game视图

3.6MenuItem菜单

3.6.1覆盖系统菜单

3.6.2自定义菜单

3.6.3源生自定义菜单

3.6.4拓展全局自定义快捷键


3拓展编辑器

3.4拓展Sence视图

3.4.1辅助元素(Gizmo)

仅在编辑模式下生效

using UnityEngine;

public class Script_03_15 : MonoBehaviour
{
    public void OnDrawGizmosSelected()
    {
        //设置颜色
        Gizmos.color = Color.red;
        //画线
        Gizmos.DrawLine(transform.position, Vector3.one);
        //立方体
        Gizmos.DrawCube(Vector3.one, Vector3.one);
    }
}

效果

参考文档

MonoBehaviour-OnDrawGizmosSelected() - Unity 脚本 API

Gizmos - Unity 脚本 API

3.4.2辅助UI

可以通过添加Editor GUI方便在视图中处理一些操作事件

示例代码

using UnityEngine;
using UnityEditor;

[CustomEditor(typeof(Camera))]
public class Script_03_16 : Editor
{
    private void OnSceneGUI()
    {
        Camera cam = target as Camera;//或者写(Camera)target,但是有可能抛出异常
        if (cam != null)
        {
            Handles.color = Color.red;
            Handles.Label(cam.transform.position,
                cam.transform.rotation.ToString());
            Handles.BeginGUI();
            GUI.backgroundColor = Color.red;
            if (GUILayout.Button("click", GUILayout.Width(200f)))
            {
                Debug.LogFormat("click = {0}", cam.name);
            }
            GUILayout.Label("Label");
            Handles.EndGUI();
        }
    }
}

效果

测试中发现Scene界面中的按钮一直出不来,检查测试之后发现是因为和上一篇的一个脚本当中的对OnInspectorGUI的内容产生了冲突,但是将两组代码合并成一个脚本后又能正常显示了。暂时还不明白这个问题的底层逻辑是什么

参考文档

Editor-OnSceneGUI() - Unity 脚本 API

3.4.3辅助常驻UI

示例代码

using UnityEngine;
using UnityEditor;

public class Script_03_17
{
    [InitializeOnLoadMethod]
    [System.Obsolete]
    static void InitializeOnLoadMethod()
    {
        SceneView.onSceneGUIDelegate = delegate (SceneView sceneView)
        {
            Handles.BeginGUI();
            GUI.Label(new Rect(0f, 0f, 50f, 15f), "标题");
            GUI.Button(new Rect(0f, 20f, 50f, 50f),
                AssetDatabase.LoadAssetAtPath<Texture>("Assets/unity.png"));
            Handles.EndGUI();
        };
    }
}

实际这段代码中使用的方法已经被最新版的unity弃用了,所以我进行了改写

using UnityEngine;
using UnityEditor;

public class Script_03_17
{
    [InitializeOnLoadMethod]
    static void SceneViewUI()
    {
        SceneView.duringSceneGui += delegate (SceneView sceneView)
        {
            Handles.BeginGUI();
            GUI.Label(new Rect(0f, 0f, 50f, 15f), "标题");
            GUI.Button(new Rect(0f, 20f, 50f, 50f),
                AssetDatabase.LoadAssetAtPath<Texture>("Assets/unity.png"));
            Handles.EndGUI();
        };
    }
}

效果

参考文档

SceneView-duringSceneGui - Unity 脚本 API

第一段代码所使用的方法我暂时也没有在之前的官方文档中找到就不放了

3.4.4禁用选中对象

using UnityEngine;
using UnityEditor;

public class Script_03_18 
{
    [InitializeOnLoadMethod]
    static void InitializeOnLoadMethod()
    {
        SceneView.duringSceneGui += delegate (SceneView sceneView)
        {
            Event e = Event.current;
            if (e != null)
            {
                int controlID = GUIUtility.GetControlID(FocusType.Passive);
                if (e.type == EventType.Layout)
                {
                    HandleUtility.AddDefaultControl(controlID);
                }
            }
        };
    }
}

添加这段代码之后将无法在Sence视图中选择任何一个物体

参考文档

FocusType - Unity 脚本 API

GUIUtility - Unity 脚本 API

3.5拓展Game视图

代码不放了主要涉及的就是怎么让Game视图在非运行模式下也绘制GUI,一般只用来做编辑器

参考文档

ExecuteInEditMode - Unity 脚本 API

3.6MenuItem菜单

3.6.1覆盖系统菜单

如果想要重写系统菜单的内容

[MenuItem("GameObject/UI/Text")]
static void CreateNewText()
{
    Debug.log("写你的功能");
}

3.6.2自定义菜单

自定义菜单能做的改动就更多了

using UnityEngine;
using UnityEditor;

public class Script_03_20
{
    [MenuItem("Root/Test1",false,1)]
    static void Test1()
    {

    }

    //菜单排序
    [MenuItem("Root/Test0", false, 0)]
    static void Test0()
    {

    }

    [MenuItem("Root/Test/2")]
    static void Test2()
    {

    }

    [MenuItem("Root/Test/2", true, 0)]
    static bool Test2Validation()
    {
        //false表示Root/Test/2菜单会置灰,不可点击
        return false;
    }

    [MenuItem("Root/Test3", false, 3)]
    static void Test3()
    {
        var menuPath = "Root/Test3";
        bool mcheched = Menu.GetChecked(menuPath); 
        Menu.SetChecked(menuPath, !mcheched);
    }
}

效果,默认选中Test3

参考文档

MenuItem - Unity 脚本 API

Menu - Unity 脚本 API

3.6.3源生自定义菜单

using UnityEngine;
using UnityEditor;
using UnityEditor.SearchService;

public class Script_03_21
{
    [InitializeOnLoadMethod]
    static void InitializeOnLoadMethod()
    {
        SceneView.duringSceneGui += delegate (SceneView sceneView)
        {
            Event e = Event.current;
            if (e != null && e.button == 1 && e.type == EventType.MouseUp)
            {
                Vector2 mousePosition = e.mousePosition;
                var options = new GUIContent[]
                {
                    new GUIContent("Test1"),
                    new GUIContent("Test2"),
                    new GUIContent(""),//分割线
                    new GUIContent("Test/Test3"),
                    new GUIContent("Test/Test4"),
                };
                //设置菜单显示区域
                var selected = -1;
                var userDate = Selection.activeGameObject;
                var width = 100;
                var height = 100;
                var position = new Rect(mousePosition.x, mousePosition.y - height, width, height);
                //显示菜单
                EditorUtility.DisplayCustomMenu(position, options, selected,
                    delegate (object data, string[] opt, int select)
                    {
                        Debug.Log(opt[select]);
                    }, userDate);
                e.Use();
            }
        };
    }
}

效果是可以在Scene界面右键调用我们创建的菜单

参考文档

EditorUtility - Unity 脚本 API

EditorUtility-DisplayPopupMenu - Unity 脚本 API

Unity 的官方文档仅收录公开稳定的接口,而 DisplayCustomMenu 是编辑器内部的工具方法,未列入正式支持列表

替代方法有很多,文档如下

GenericMenu - Unity 脚本 API

EditorWindow - Unity 脚本 API

IHasCustomMenu - Unity 脚本 API

3.6.4拓展全局自定义快捷键

基础语法

[MenuItem("Tools/Delete Selected Objects %#d")]
static void DeleteSelected()
{
    foreach (var obj in Selection.gameObjects)
        Object.DestroyImmediate(obj);
}

参考文档

MenuItem-MenuItem - Unity 脚本 API

Logo

纵情码海钱塘涌,杭州开发者创新动! 属于杭州的开发者社区!致力于为杭州地区的开发者提供学习、合作和成长的机会;同时也为企业交流招聘提供舞台!

更多推荐