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

第三章自定义检视面板_创建自定义编辑器类_实现自定义检视面板中的GUI内容(本章进度(1/9))

3.1创建自定义编辑器类

3.1.1 如何实现自定义检视面板中的GUI内容

Editor类中的虚方法OnInspectorGUI()定义了组件的检视面板如何绘制,重写该方法可实现自定义,想要拓展的话,则要保留base.OnInspectorGUI。它不止可以用于自定义的组件,同时unity自带的组件也可以,比如Tranform之类的。
我们已经有了Mono类,为什么还要实现OnInspector(),我们如果自定义编辑器类操作字段,需要四步

  • 1.需要先获取到指定类的指定字段,
  • 2.显示到inpector面板
  • 3.将面板上修改的值,赋值给指定字段
  • 4.数据需要调用api实现修改数据保存。
    一下多了四步,而如果使用Mono,我们不需要做这些四步,我们为什么要费劲做四步呐,他的好处是什么,初学的时候,也困惑我一阵,但其实看似多走了很多步,但是长远来看,拓展出的工具却是节省了更多时间,下面是一些区别。
特性OnInspectorGUI() 自定义默认 MonoBehaviour 字段
布局控制完全自由定制固定顺序排列
功能扩展可添加按钮、滑块、预览区等复杂控件仅显示基础字段
撤销支持完整支持 (Ctrl+Z 回退所有操作)部分支持 (仅序列化字段)
多对象编辑同时批量修改多个选中对象有限支持 (仅公共字段)
安全封装保持私有字段不可见,不破坏封装性需要暴露字段才能显示
内置组件扩展可为Transform等系统组件添加功能无法扩展系统组件
开发效率需额外编写编辑器代码零配置自动显示

以下是举个显示在自定义组件字段的例子

1.首先定义这个自定义组件

代码如下

using UnityEngine;public class CustomComponent : MonoBehaviour
{//在 Unity 编辑器扩展中,访问目标组件字段的途径有两种//​​1.通过序列化系统​​:可访问标记为 public(Unity会自动序列化public字段) 或添加了 [SerializeField] 特性的字段//​2.​通过反射​​:可访问任意访问修饰符的字段(包括 private/protected),但需手动处理数据持久化//他们的具体区别看下表吧,一般来说都是通过第一种, 第二种很少用。public int intValue;[SerializeField] private  string stringValue;[SerializeField] private bool boolValue;[SerializeField] private GameObject go;public enum ExampleEnum{Option1,Option2,Option3}[SerializeField] private ExampleEnum exampleEnum;
}
特性序列化系统反射
字段可见性public / [SerializeField]任意(含private)
撤销支持✅ 自动❌ 需手动实现
多对象编辑✅ 自动同步❌ 需遍历targets
数据持久化✅ 自动标记脏数据❌ 需调用SetDirty()
重命名安全✅ 通过属性名查找❌ 硬编码字符串易断裂
性能⭐⭐⭐⭐ 高效⭐ 反射开销较大

2.显示在InSpector面板以及将面板上修改的值,赋值给指定字段

在这里我们一下完成了第二步和第三步,我们需要使用一个特性CustomEditor用来作用于组件。这里需要理解一下SeriailizedProperty这个类,他是我们用来操作数据的中介类,通过他来获取,修改。
SerializedProperty点击跳转

using System.Reflection; // 引入反射命名空间,用于访问私有字段
using UnityEditor;       
using UnityEngine;     /// <summary>
/// 使用CustomEditor特性,指定这个编辑器类是为CustomComponent组件服务的
/// </summary>
[CustomEditor(typeof(CustomComponent))]
public class CustomCompoentEditor : Editor
{private CustomComponent component; // 当前正在编辑的CustomComponent组件实例// 序列化属性,用于访问和修改组件中的序列化字段private SerializedProperty stringValueProperty; // 字符串类型字段private SerializedProperty gameObjectProperty;  // GameObject类型字段private SerializedProperty enumValue;           // 枚举类型字段// 反射字段信息,用于访问私有字段private FieldInfo boolValueFieldInfo; // 布尔类型私有字段// 当编辑器启用时调用,用于初始化private void OnEnable(){/*这里只是为了演示不同的获取方式 一种当字段是public时可以直接访问,或者被[serilaredField]*///工作原理就是从target中获取到当前正在编辑的组件实例,然后去查找指定字段// 获取当前正在编辑的组件实例component = (CustomComponent)target;// 通过序列化对象查找并获取各个序列化属性stringValueProperty = serializedObject.FindProperty("stringValue"); // 查找字符串字段,这里不是反射,是unituy序列化系统gameObjectProperty = serializedObject.FindProperty("go");           // 查找GameObject字段enumValue = serializedObject.FindProperty("exampleEnum");           // 查找枚举字段// 初始化反射字段,这里用到了反射,只是为了演示所以用到反射boolValueFieldInfo = component.GetType().GetField("boolValue",BindingFlags.NonPublic | BindingFlags.Instance);}/// <summary>/// 重写OnInspectorGUI方法,自定义Inspector界面/// </summary>public override void OnInspectorGUI(){CustomExample(); // 调用自定义的绘制方法}/// <summary>/// 自定义绘制Inspector界面的方法/// </summary>private void CustomExample(){// 绘制公共整数字段component.intValue = EditorGUILayout.IntField("Int Value", component.intValue);/** EditorGUILayout.IntField:* 创建一个整数输入字段* 参数1:"Int Value" - 显示在字段前的标签* 参数2:component.intValue - 当前整数值* 返回值:用户输入的新整数值*/// 绘制字符串输入字段stringValueProperty.stringValue = EditorGUILayout.TextField("String Value",stringValueProperty.stringValue);/** EditorGUILayout.TextField:* 创建一个文本输入框* 参数1:"String Value" - 显示在输入框前的标签* 参数2:stringValueProperty.stringValue - 当前字符串值* 返回值:用户输入的新字符串*/// 绘制私有布尔字段(通过反射访问)boolValueFieldInfo.SetValue(component,EditorGUILayout.Toggle("Bool Value",(bool)boolValueFieldInfo.GetValue(component)));/** EditorGUILayout.Toggle:* 创建一个布尔值开关(复选框)* 参数1:"Bool Value" - 显示在开关前的标签* 参数2:(bool)boolValueFieldInfo.GetValue(component) - 当前布尔值* 返回值:用户设置的新布尔值* * boolValueFieldInfo.SetValue:* 通过反射将新值设置回组件的私有字段*/// 绘制枚举下拉选择框enumValue.enumValueIndex = EditorGUILayout.Popup("Enum Value",enumValue.enumValueIndex,enumValue.enumNames);/** EditorGUILayout.Popup:* 创建一个下拉选择框* 参数1:"Enum Value" - 显示在下拉框前的标签* 参数2:enumValue.enumValueIndex - 当前选中的枚举值索引* 参数3:enumValue.enumNames - 所有枚举值名称的字符串数组* 返回值:用户新选择的索引*/}
}

运行效果图
在这里插入图片描述

http://www.dtcms.com/a/285319.html

相关文章:

  • 「源力觉醒 创作者计划」_巅峰对话:文心 4.5 vs. DeepSeek / Qwen 3.0 深度解析(实战优化版)
  • 【NLP舆情分析】基于python微博舆情分析可视化系统(flask+pandas+echarts) 视频教程 - jieba库分词简介及使用
  • CVSS 3.1权限要求(PR)深度解读
  • 信息论至AI实践:交叉熵的原理全景与应用深度解析
  • 苹果ios系统IPA包企业签名手机下载应用可以有几种方式可以下载到手机?
  • 时序数据库 Apache IoTDB 实战:基于 Kubernetes 的部署运维全指南
  • 固件OTA升级常见问题
  • 9. isaacsim4.2教程-ROS加相机/CLOCK
  • Onload 用户指南 (UG1586)-笔记
  • (数据结构)线性表(上):SeqList 顺序表
  • Mysql数据库——增删改查CRUD
  • k8s:利用kubectl部署postgis:17-3.5
  • Java面向对象核心揭秘:从构造到多态的实战指南
  • Java List 集合详解:从基础到实战,掌握 Java 列表操作全貌
  • 代码随想录算法训练营65期第22天
  • 五分钟学会大数定律【笔记】
  • day055-Dockerfile与常用指令
  • 上网行为管理之内容审计实验
  • 数据结构-2(链表)
  • 基于强化学习的人机协同教学角色分配优化与课堂参与度建模研究
  • C++拷贝构造
  • 鸿蒙UI自动化测试框架Hypium的使用指南
  • Netty入门学习
  • java-字符串和集合
  • (自用)补充说明2
  • 《python语言程序设计》2018版第8章8题编写函数实现二进制转十进制(字符串变整数)!!整数没法进行下标
  • 基于MATLAB的极限学习机ELM的数据回归预测方法应用
  • 用python可视化分析二次元经济的爆发
  • python网络爬虫(第一步:网络爬虫库、robots.txt规则(防止犯法)、查看获取网页源代码)
  • 2025年6月GESP(C++一级):假期阅读