• 友链

  • 首页

  • 文章归档
h u a n b l o g
h u a n b l o g

欢

HI,Friend

01月
24
Unity

Unity编辑器扩展二

发表于 2022-01-24 • 字数统计 9517 • 被 1,097 人看爆

编辑器扩展一

inspector面板

使用EditorGUILayout进行绘制,Editor文件下

成员变量的显示

在成员变量前使用Attribute修改该变量,使其可以在inspector面板上进行序列化
  • [SerializeField]:一般修饰 private和protected 变量,来达到序列化私有和保护变量的目的,从而可以在Inspector面板中显示和编辑。防止仅仅想让其在Inspector面板中显示而导致public变量滥用。
  • [NonSerialized]:一般修饰public变量,来达到不被序列化的目的,且不在Inspector面板中显示。
  • [HideInInspector]:一般修饰public变量,来达到不在Inspector面板中显示的目的
  • [Serializable]:用在类的前面,表示该类可被序列化

总结

  • 被序列化的值可以在Inspector面板上显示,反之则不能。变量本身通过访问权限可以知道是否被序列,在此之外还可以使用[SerializeField] [NonSerialized] [Serializable] 这几个Attribute改变序列化与不被序列化。
  • 被序列化的值也可以不在Inspector面板中显示,使用[HideInInspector]特性来隐藏。
  • 不被序列化的值是不可以在Inspector面板中显示的。

自定义的inspector面板

CustomEditor

就是告诉编辑器要对该类所在的inspector面板进行操作

用法

//用于对LookAtPoint组件所在inspector面板进行扩展
[CustomEditor(typeof (LookAtPoint))]    

OnInspectorGUI

用于实现扩展功能,比如说label,Toggle等功能,只能在该方法先实现
using UnityEditor;
public class EditorScritp : Editor {
    public override void OnInspectorGUI()
    {

        GUILayout.Label("This is a Label in a Custom Editor");
    }
}

上面完整代码

using UnityEditor;
//用于对LookAtPoint组件所在inspector面板进行扩展  LookAtPoint非Editor脚本,而是常用组件脚本
[CustomEditor(typeof (LookAtPoint))]  
public class EditorScritp : Editor {
    public override void OnInspectorGUI()
    {

        GUILayout.Label("This is a Label in a Custom Editor");
    }
}

效果如下
EditorExtension13.png

CanEditMultipleObjects

用于选中多个物体在同一类型组件上修改

用法

和CustomEditor一样,放在类上面

没添加情况下
EditorExtension14.png
选择多个不会显示输入框

添加了情况下
EditorExtension15.png

属性

常用于显示在inspector面板的,平常只能定义一些常用属性,使用编辑器扩展可以定义多种样式,比如说:纹理,展示图片等
分成两个脚本,继承自MonoBehaviour用于定义属性,继承自Editor类用于定义显示样式

SerializedProperty/SerializedObject

SerializedProperty:用于对属性进行编辑
SerializedObject:对修改的属性进行刷新等操作
两者搭配使用

数组/List

PropertyField

通过PropertyField简单显示数组或者集合,通过EditorGUILayout访问
//继承自MonoBehaviour
[ExecuteInEditMode]         //让脚本在编辑模式下也可以运行
public class LookAtPoint : MonoBehaviour {

    //序列化
    [SerializeField]
    public int[] intArray;
    [SerializeField]
    public List<string> stringList;

}

//继承自Editor
[CustomEditor(typeof (LookAtPoint))]
public class EditorScritp: Editor
{

    private SerializedProperty intArray;
    private SerializedProperty stringList;

    private void OnEnable()
    {
        //按照名称查找属性
        intArray = serializedObject.FindProperty("intArray");
        stringList = serializedObject.FindProperty("stringList");
    }

    public override void OnInspectorGUI()
    {
        //更新序列化的显示方式
        serializedObject.Update();
        //绘制样式
        EditorGUILayout.PropertyField(intArray, true);
        EditorGUILayout.PropertyField(stringList, true);
        //对修改的属性进行应用
        serializedObject.ApplyModifiedProperties();
    }
}

效果如下
EditorExtension18.png

ReorderableList

实现可排序列表,可通过鼠标拖动,修改列表元素的排列顺序,注意其命名空间为UnityEditorInternal
由于其是内部使用,所以没有记录早Unity文档里
[ExecuteInEditMode]         //让脚本在编辑模式下也可以运行
public class LookAtPoint : MonoBehaviour {

    [SerializeField]
    public List<string> stringArray;


}

using UnityEditor;
using UnityEditorInternal;
using UnityEngine;

[CanEditMultipleObjects]
[CustomEditor(typeof (LookAtPoint))]
public class EditorScritp: Editor
{

    private SerializedProperty stringArray;
    private ReorderableList _stringArray;

    private void OnEnable()
    {
        //按照名称查找属性
        stringArray = serializedObject.FindProperty("stringArray");
        _stringArray = new ReorderableList(serializedObject, stringArray, true, true, true, true);
        _stringArray.drawElementCallback = DrawNameElement;

    }

    //绘制元素 添加输入框
    private void DrawNameElement(Rect rect, int index, bool selected, bool focused)
    {
        SerializedProperty itemData = _stringArray.serializedProperty.GetArrayElementAtIndex(index);
        rect.y += 2;
        rect.height = EditorGUIUtility.singleLineHeight;
        EditorGUI.PropertyField(rect, itemData, GUIContent.none);
    }

    public override void OnInspectorGUI()
    {
        //更新序列化的显示方式
        serializedObject.Update();
        _stringArray.DoLayoutList();
        //对修改的属性进行应用
        serializedObject.ApplyModifiedProperties();


    }
}

效果如下
EditorExtension19.png
就可以实现拖动效果了
详情可查看底部文章链接

变量

名称描述
draggable拖曳排序
displayAdd显示添加按钮
displayRemove显示移除按钮
elementHeight元素高度
headerHeight表头高度
footerHeight尾部高度
showDefaultBackground显示默认背景

公有方法

名称描述
DoLayoutList自动布局绘制列表
DoList(Rect rect)指定区域绘制列表
GetHeight获取绘制列表总高度

委托

名称描述
drawHeaderCallback绘制表头回调
drawFooterCallback绘制尾部回调
drawElementCallback绘制元素回调
drawElementBackgroundCallback绘制元素背景回调
onReorderCallback重新排序回调
onSelectCallback选中回调
onAddCallback添加按钮回调
onAddDropdownCallback添加下拉选项回调
onRemoveCallback移除元素回调
onMouseUpCallback鼠标抬起回调
onCanRemoveCallback是否显示可移除按钮回调
onChangedCallback列表改变回调

PropertyDrawer

绘制列表元素,在OnGUI方法下使用
参考官网

Gizmos

是Scene场景的可视化调试或辅助工具。脚本放在Gizmos文件夹下,继承于monobehaviour类,通过OnDrawGizmo或者OnDrawGizmosSelected实现
  • OnDrawGizmo:用于每帧调用,使用相对场景视图鼠标的位置
  • OnDrawGizmosSelected:脚本附加的对象被选中时才会被调用。例如:可以绘制一个显示爆炸半径的球体
//在一个空的Object上绘制Cube
 //绘制效果一直显示
private void OnDrawGizmos()
{
    var color = Gizmos.color;
    Gizmos.color = Color.white;
    Gizmos.DrawCube(transform.position, Vector3.one);
    // Gizmos.color作为全局的静态变量,为了防止这里的color修改会对其他地方的绘制造成影响,所以在绘制完Gizmos的时候,将Gizmos.color修改为原先的值。
    Gizmos.color = color;
}

//绘制效果在选中对象时显示
private void OnDrawGizmosSelected()
{
    var color = Gizmos.color;
    Gizmos.color = Color.white;
    Gizmos.DrawWireCube(transform.position, Vector3.one);
    // Gizmos.color作为全局的静态变量,为了防止这里的color修改会对其他地方的绘制造成影响,所以在绘制完Gizmos的时候,将Gizmos.color修改为原先的值。
    Gizmos.color = color;
}

效果如下
EditorExtension16.png

特性

DrawGizmo,为任何组件使用Gizmo。是Editor下,

用法

放在方法上,满足条件则执行方法,方法为static
DrawGizmo(GizmoType gizmo, Type drawnGizmoType);
  • 第一个参数:什么时候绘制
  • 第二个参数:绘制的对象类型
[DrawGizmo(GizmoType.NotInSelectionHierarchy | GizmoType.Pickable)]
static void drawGizmo1(Light light, GizmoType gizmoType)
{
    Vector3 position = light.transform.position;

    Gizmos.DrawIcon(position + Vector3.up, "ninja.jpg");
}

什么时候绘制

GizmoType描述
Active激活时,绘制
InSelectionHierarchy选中时或者其子节点被选中时,绘制
Selected选中时,绘制
NonSelected未选中时,绘制
NotInSelectionHierarchy未选中时或者其子节点未被选中时,绘制
Pickable在编辑器中选中时,绘制

常用方法

  • Gizmos.DrawCube():绘制实体立方体
  • Gizmos.DrawWireCube(): 绘制立方体边框
  • Gizmos.DrawRay():绘制射线
  • Gizmos.DrawLine():绘制直线
  • Gizmos.DrawIcon():绘制Icon,Icon素材需要放在Gizmos文件夹中
  • Gizmos.DrawFrustum():绘制摄像机视椎体的视野范围

Scene视图

为Scenes视图添加功能,命名空间是using UnityEditor; OnSceneGUI方法内编写, Handles绘制句柄
如果想要绘制GUI,则必须要在BeginGUI、EndGUI的方法对中
using UnityEditor;
using UnityEngine;

[CanEditMultipleObjects]
[CustomEditor(typeof (LookAtPoint))]
public class EditorScritp: Editor {

    //获取SceneExt脚本对象
    private LookAtPoint _target { get { return target as LookAtPoint; } }

    private void OnSceneGUI()
    {
        //操作句柄
        Handles.Label(_target.transform.position, _target.transform.name + " : " + _target.transform.position);

        //绘制GUI的内容必须要在BeginGUI、EndGUI的方法对中
        Handles.BeginGUI();
        //设置GUI绘制的区域
        GUILayout.BeginArea(new Rect(50, 50, 200, 200));
        GUILayout.Label("Scene 扩展练习");
        GUILayout.EndArea();
        Handles.EndGUI();
    }
    
}

效果如下
EditorExtension17.png

参考

  • 官网-扩展编辑器
  • ivy_0709-Unity编辑器扩展之Component的Inspector面板
  • 庸人自扰Eam-Unity Editor 基础篇(二):自定义 Inspector 面板
  • 虚拟喵-Unity 编辑器扩展总结 五:Gizmos辅助调试工具

ReorderableList

  • Valentin Simonov-Unity: make your lists functional with ReorderableList
  • 虚拟喵-Unity 编辑器扩展总结 七:数组或list集合的显示方式
  • 无幻-Unity ReorderableList 可重新排序的列表框使用
  • 弹吉他的小刘鸭-Unity的Reorderable List用法
分享到:
Unity数据保存
页面置换算法
  • 文章目录
  • 站点概览
欢

网红 欢

你能抓到我么?

Email RSS
看爆 Top5
  • mac系统版本与Xcode版本有冲突 3,840次看爆
  • JAVA_HOME环境配置问题 3,551次看爆
  • AssetBundle使用 3,289次看爆
  • VSCode配置C++开发环境 3,058次看爆
  • Lua反射 3,010次看爆

Copyright © 2025 欢 粤ICP备2020105803号-1

由 Halo 强力驱动 · Theme by Sagiri · 站点地图