当前位置: 首页 > article >正文

【Unity编辑器】拓展Inspector视图

目录

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来延迟一帧调用


http://www.kler.cn/news/17824.html

相关文章:

  • 【Python百日进阶-Web开发-Feffery】Day617- 趣味dash_17:微型系统--引入flask-login
  • vue+node.js高校青年志愿者管理系统
  • AI来势汹汹,这份「生存计划」请查收!
  • 搭建vue3+vite工程
  • HTTPS协议介绍
  • 4.4——多重继承
  • 树形结构的三级分类如何实现?
  • 如何训练自己的大型语言模型
  • powershell定义文本,用户交互,正则表达式
  • 宝塔面板搭建自己的网站,并发布公网远程访问
  • 企业服务管理(ESM)工具
  • MySQL中的Join 的算法(NLJ、BNL、BKA)
  • XXLJOB
  • 知识变现海哥|这3种课程定价最容易爆单
  • asp.net+sqlserver企业财务管理系统
  • 【Mybatis】增删改查
  • 北斗导航 | 基于差分法的周跳探测(matlab 代码)
  • android pdf框架
  • unity航点寻径
  • js中对象和数组的都是如何解构的
  • 二挡起步——pythonweb开发Django框架,前端原生+Django后端框架+python网络抓包(代替数据库数据)(附带小案例)
  • Java学习之Swing图形界面
  • 关于面试官问Qt Connect的链接方式和类型问题
  • jQuery -- 常用API(下)
  • 《Netty》从零开始学netty源码(五十二)之PoolThreadCache
  • SpringBoot整合FreeMarker
  • 使用zabbix监控Windows指定服务| zabbix Windows service filter
  • 【网络】4万字细品TCP协议
  • yolov8 OpenCV DNN 部署 推理报错
  • 科大版中国版ChatGPT来啦!抢先体验